2008/02/13

[Programming] pttget.pl

備份~ 抓 ptt 上面文章的 perl script (從 kenwu 那邊修改的,好像有點小問題,我也忘了~)

#!/usr/bin/perl
#
# PTT BBS Board Crawler BETA 3, Powered By LiloHuang
# http://blog.roodo.com/kenwu/
# 使用 GPL V2 釋出擷取文章功能部份程式
# Last Updated: 2007/09/02
#
# Fix: 修正 guest無法登入問題
#

$|=1;
use strict;
use Net::Telnet;
use Time::HiRes qw(usleep);

system("title KUSO PTT BBS Board Crawler BETA 3");
print "########################################\n";
print "# KUSO PTT BBS Board Crawler BETA 3 #\n";
print "# Powered By LiloHuang #\n";
print "# http://blog.roodo.com/kenwu/ #\n";
print "########################################\n\n";
print "說明: 這是一個可以將 PTT BBS看板進行抓取的程式...\n";
print " 目前仍在測試階段, 還有許\多Bug與不穩定...\n";
print " 僅供測試使用, 切莫用於非法用途侵權他人文章!!\n\n";

my $host;
print "站台: \n";
print " 1. ptt.cc\n";
print " 2. ptt2.cc\n";
print "請選擇: ";
my $site = 1; #;
chomp $site;
$host = ($site eq '1'?"ptt.cc":"ptt2.cc");
mkdir("./$host") unless(-d "./$host/");
print "\nBBS 帳號: ";
my $id = "我的帳號"; #;
chomp $id;
&except("沒有輸入帳號, 程式即將關閉.") if($id eq '');
print "BBS 密碼: ";
my $pass = "我的密碼"; #;
chomp $pass;
print "看板名稱: ";
my $board = "Sodagreen"; #;
chomp $board;
&except("沒有輸入看板名稱, 程式即將關閉.") if($board eq '');
print "起始文章編號: ";
my $start = 8435; #;
chomp $start;
&except("沒有輸入起始編號, 程式即將關閉.") if($start eq '');
print "結束文章編號: ";
my $end = 8436; #;
chomp $end;
&except("沒有輸入結束編號, 程式即將關閉.") if($end eq '');
&except("結束編號 < 起始編號, 邏輯錯誤, 程式即將關閉.") if($end<$start);

my $num = $end - $start + 1;
my $esc = chr(27);
my @stack;
my $buf;
my $cnt;
my $bot;
my $rec = 0;
my $bar = '─'x39;

my %login = (
"請輸入代號" => "$id\n",
"請輸入您的密碼" => "$pass\n",
"您想刪除其他重複的" => "N\n",
"錯誤嘗試" => "\n",
"任意鍵" => "\n",
"酸甜苦辣板" => "q",
"鴻雁往返" => "q"
);

my %board = (
"任意鍵" => "\n",
);

print "\n正在登入 $host...";
&build;
while( $buf = &get ) {
if($buf =~/由於人數過多,請您稍後再來。/) {
print "線上人數過多, 自動重新連線第 ".sprintf("%3d",++$rec)." 次\r";
$bot->close;
&build;
}
&except("目前已有太多 guest 在站上") if($buf =~/目前已有太多 guest 在站上/);
&except("這裡沒有這個人啦!") if($buf =~/這裡沒有這個人啦/);
&except("密碼不對喔") if($buf =~/密碼不對喔/);
last if($buf =~/.+目前坊裡有.+?$/);
foreach (keys %login) {
&put($login{$_}) if($buf=~/$_/);
}
}
print "Done!\n";

print "進入 $board 看板...";
&put("s");
usleep(1000);
&put("$board\n");
while( $buf = &get ) {
last if($buf =~/文章選讀/);
foreach (keys %login) {
&put($login{$_}) if($buf=~/$_/);
}
}
print "Done!\n\n";

$cnt = 0;
&put("$start\n\n");

mkdir("./$host/$board") unless(-d "./$host/$board/");

while( $buf = &get ) {
last if($buf =~/文章選讀/);
push(@stack, $buf);
print "正在擷取第 ".sprintf("%3d",($cnt+1))." 篇文章...\r";
unless( $buf !~ /\Q (100%)\E/)
{
&callback($start+$cnt);
undef @stack;
last if ++$cnt==$num;
}
&put(".");
}
print "\n\n總共 $cnt 文章擷取完畢\n\n";
$bot->close;
system("PAUSE");

sub callback {
open(FH,">./$host/$board/$_[0].ans");
my @out_buffer;
my $pos = 0;
for(my $i=0;$i<=$#stack;$i++) {
my @tmp = split(/\n/, $stack[$i]);
$tmp[0]=~s/^$esc\[H$esc\[J/$i==0?"":"\n"/e;
my $linetag = pop @tmp;
if($i > 0 && $i==$#stack) {
if($i < 2) {
if($linetag=~/目前顯示: 第 (\d+)~(\d+) 行/) {
my $rexp_s = $1;
$rexp_s = $rexp_s - 1 if($stack[$i]=~/$esc\[36m$bar$esc\[m/);
foreach(@tmp) {
s/$esc\[\d+;\d+H/\n/;
$out_buffer[$rexp_s++] = $_;
}
}
}else{
shift(@tmp) if($i>0);
foreach(@tmp) {
s/$esc\[\d+;\d+H/\n/;
$out_buffer[$pos++] = $_;
}
}
}else{
shift(@tmp) if($i>0);
foreach(@tmp) {
$out_buffer[$pos++] = $_;
}
}
}

foreach(@out_buffer) {
s/$esc\[K//g;
s/\r/\n/g;
print FH $_;
}
close(FH);
}

sub put {
$bot->put($_[0]);
usleep(200000);
}

sub get {
usleep(200000);
return $bot->get( Timeout => 10000 );
}

sub error {
print "網路連線逾時或程式發生異常, 程式即將關閉!\n\n";
system("PAUSE");
$bot->close;
exit;
}

sub except {
print "$_[0]\n\n";
system("PAUSE");
exit;
}

sub build {
$bot = new Net::Telnet (
Port => 23,
Timeout => 30,
Errmode => \&error
);
$bot->open($host);
}

7 則留言:

ballboy 提到...

你好! 我最近有試過! 好像不行!
好像連登入到ptt都沒辦法~
請問你有試成功嗎?

anton 提到...

hi:

剛剛驗證了一下,這個 script 雖然過時了,但是還是很有參考價值喔。關鍵字修改一下就還可以可以用的。

Unknown 提到...

不好意思 最近剛好在研究從ptt擷取文章下來
試了一下你的程式 但好像無法成功執行
想請問這個程式碼目前還是work的嗎?
或是除了帳號/密碼/看板名稱/起訖文篇號碼 還有其他須調整的部分?
再麻煩你了 謝謝!!!

errMsg為'正在登入 ptt.cc...網路連線逾時或程式發生異常, 程式即將關閉!'

anton 提到...

給周梅:
"請輸入代號"也要跟著 bbs 的站台登入提示一起更新。

Unknown 提到...

想請問一下 這邊的代號指的是什麼?
是我登入BBS的帳號密碼嗎
不太懂 謝謝你!!

anton 提到...

輸入帳密之前的提示,所以如果你是抓 ptt.cc ,那就是登入 ptt.cc 之前的提示語。
像:

請輸入帳號:
請輸入密碼:


又或著,舉例來說,就是像 expect script 裡頭的 expect keyword.

Unknown 提到...

謝謝你 看來連線是成功了,在本機也會建立一個ptt.cc的資料夾
不過感覺他會停留在登入的階段
這樣是正常的嗎?
不好意思 再麻煩你解答了!!

畫面資訊如下:
站台:
1. ptt.cc
2. ptt2.cc
請選擇:
BBS 帳號: BBS 密碼: 看板名稱: 起始文章編號: 結束文章編號:
正在登入 ptt.cc...

[Windows] git-bash 底下的工具

因為工作轉到 Windows 平台上的關係,所以很多工具改到 Windows 上面運作,跟著在 TortoiseGit 底下使用 git-bash 來維護自己的專案原始碼。結果就是裝了前面提過的 auto-hotkey 使用熱鍵來提昇自己的平台操作速度; 但除了 hotkey...