iT邦幫忙

0

[求教] 用Perl 抓取網頁Link 的一個疑問?

use LWP::Simple;
use HTML::Parse;
use HTML::Element;

$url ="http://靜態網頁";
$html = get($url);

$parsed_html = parse_html($html);
for (@{ $parsed_html->extract_links() })
{
        $link = $_->[0];
        print "$link\n";
}

若url 換成動態網頁

ex: http://www.softking.com.tw/soft/download.asp?fid3=23516

這個時候就沒有效果了

請IT幫幫忙 !

謝謝

看更多先前的討論...收起先前的討論...
powerop 的網頁,以wget的測試的過程有點誤差,
因所抓的網址是 clickcount.asp 而不是 download.asp,
而抓 clickcount.asp 的網頁,什麼參數都不加都可以抓。

用 Google 搜尋:
site:www.softking.com.tw/soft/download.asp?
基本上沒有幾筆且都是 「操作錯誤,網站瀏覽已被限制暫停!Q」的頁面。
而 site:www.softking.com.tw/soft/ 都已順利抓到 clickcount.asp 的頁面。
而 softking 的網頁的連結,都是 clickcount;
所以結論是 download.asp 好像是 softking 的舊連結,
可能只是作為因應網路上以前留下許多舊連結,
來做導到 新網址的作用 而已。
wget, curl, LWP,應都是只處理 HTML,
而不會去處理 javascript,
或者說視為 comments 之類。
而該網頁 http://www.softking.com.tw/soft/download.asp?fid3=23516
並沒有 <NOSCRIPT> 的內容,
所以就算是 Google 等 robots,
也只會抓到該頁,而不會再往 javascript 所指的 location 抓下去。
就算用 lynx, links 之類的 text-based browser,
對只有 javascript 的頁面而沒有透過 NOSCRIPT 提供連結的話,
也一樣只有一片空白。
所以,想要把 javascript 裡所導到其他的連結,
應與 cookies, referer 沒有關係,
在於去抓取該網頁的工具,有無去處理 javascript 的能力。
所以若要用 perl 來抓取之後的網頁或連結,
只能用事後諸葛的方式,擷取 javascript 裡 location 後面的字串,
視之為是一個連結,來做額外處理。
在 wget 的 FAQ 裡 3.6 Does Wget understand JavaScript?,是說 wget 應不認得 javascript,
但該 FAQ 網頁太久沒更新,所以也不大準,
而從 JavaScript Functionality For Wget
看起來是說要用 plugin 的方式,讓 wget 有一些可以認一些javascript;
但目前所用的 wget 應都還是不會認 javascript。

而powerop 的網頁測試,先抓 clickcount.asp 並存其 cookies 後,
之後再 load cookies 確實能夠把 download.asp 抓下。
我也很好奇,到底是 wget 認得 javascript 嗎?
自己再用 Firefox 測試,首先啟用 NoScript,並用 Add N Edit Cookies ,
把所有 softking 的 cookie 砍掉,
直接連 http://www.softking.com.tw/soft/download.asp?fid3=23516 ,
因沒啟動 Javascript 所以一片空白,再 reload 幾次也一樣。
再開個分頁到 http://www.softking.com.tw/,
再 reload 剛才的 download.asp ,也還是一樣,
再從 softking 隨便點一個 clickcount.asp 後,
再 reload 剛才的 download.asp ,就可以看到畫面了。

所以代表的是 當點 clickcount 時,在 cookie 中寫入了:
xx=xx (觀察一下 cookie 的變化,是寫了什麼值…)
而 download.asp 看到 cookie 有這個值就直接載入頁面,
若沒有該值,就以只有 javascript 的畫面畫面。

所以只要
wget --header "Cookie: xxx=xxx" http://www.softking.com.tw/soft/download.asp?fid3=23516
就可以抓到頁面了。

結論是:download.asp是靠 cookie 的檢查來決定直接秀出網頁,或畫出 javascript 的畫面。
16
逮丸逮丸
iT邦大師 1 級 ‧ 2009-05-28 20:50:41
最佳解答

根據討論中的結論,再改寫原來的程式碼為:

&lt;pre class="c" name="code">
#use LWP::Simple;
use HTML::Parse;
use HTML::Element;
use LWP::UserAgent;

$ua = LWP::UserAgent->new;
$url ="http://www.softking.com.tw/soft/download.asp?fid3=23516";
$req = HTTP::Request->new(GET => $url);
$req->header(Cookie => 'download=download');

#$html = get($url);
$html = $ua->request($req);
#print $html->content, "\n";
$parsed_html = parse_html($html->content);
for (@{ $parsed_html->extract_links() })
{
        $link = $_->[0];
        print "$link\n";
}

就可以做到想要的結果了。

16
pcboy
iT邦高手 1 級 ‧ 2009-05-27 18:52:52

您的 $html 應該抓到下面部分

<SCRIPT LANGUAGE = "JavaScript">
<!--
{
alert("■ 網頁提示 ■\n\n◆您瀏覽器的功能 Cookies 未開啟,或您不可直接由此進入網頁\n\n◆將帶您回到該軟體的說明網頁,您再進入此網頁\n\n◆若您再進入網頁仍看到此訊息,表示您的 Cookies 功能真的該打開了");
window.parent.location.href="/soft/clickcount.asp?fid3=23516";
}
//-->
</Script>

parse_html 是否有能力抓出 /soft/clickcount.asp?fid3=23516 就很難說了

這是 parser 程式寫的好壞和功力的問題

20
powerop
iT邦研究生 4 級 ‧ 2009-05-28 01:15:26
看更多先前的回應...收起先前的回應...
pcboy iT邦高手 1 級 ‧ 2009-05-28 08:18:26 檢舉

實驗不對,發問者是說下面網址無效果
http://www.softking.com.tw/soft/download.asp?fid3=23516

結果實驗卻去直接測試它剖析不出來的網址
/soft/clickcount.asp?fid3=23516

pcboy iT邦高手 1 級 ‧ 2009-05-28 08:34:54 檢舉

修正網址,測試 mirror抓十層

測試(a)
wget -m --level=10 --cookies=on --keep-session-cookies --save-cookies=cookie.txt http://www.softking.com.tw/soft/download.asp?fid3=23516

測試(b)
wget -m --level=10 --referer=http://www.softking.com.tw/soft/download.asp?fid3=23516 --cookies=on --load-cookies=cookie.txt --keep-session-cookies --save-cookies=cookie.txt http://www.softking.com.tw/soft/download.asp?fid3=2351

只能抓到 download.asp@fid3=23516 檔案而已,表示無法從 download.asp?fid3=23516 中剖析出 clickcount.asp?fid3=23516" 繼續抓下去

lalelee iT邦新手 4 級 ‧ 2009-05-28 10:48:01 檢舉

謝謝您的費心實驗,我跟您一樣唯二的兩個程式語言工具就是sh and perl ,呵呵~

其實我的QBQ是這樣的,我在玩LWP::SIMPLE這個Package
我想試著寫出一個程式是類似wget可以抓取某網頁上所有的檔案,LWP裡面的getstore()已經可以將link存檔了,所以我只要能將網頁上的link通通parse出來就好了,只是沒想到會碰到http refer跟cookies的保護,您提供的方法可以讓我將下載的網頁抓出來,我做個實驗應該可以用RE將所有http link列出來

謝謝 保持聯絡

msn: lale.lee@msa.hinet.net

lalelee iT邦新手 4 級 ‧ 2009-05-28 22:10:42 檢舉

$req->header(Cookie => 'download=download');

這段不太了解,請問為何知道Cookie 該設'download=download' ??

謝謝

參閱 http://ithelp.ithome.com.tw/question/10021692?tab=opinion&oid=85801#85801
當清空 softking cookie後,點 download.asp 多兩個值,無效;而再點 clickcount.asp 又多了兩個值,才有效;就試這兩個值之中,哪一個有效,就找到了。

powerop iT邦研究生 4 級 ‧ 2009-05-31 00:13:25 檢舉

iT邦 這邊大家的回應都很精彩,我又 拋磚引玉 囉 :D
(嗚嗚,哪天才能拼到下一題最佳解答啊 XD)

我要發表回答

立即登入回答