自動抓網頁

Posted by tjwei on 星期五, 4月 20, 2007 with No comments
或多或少,總是有人會有需求,把一些網頁抓下來作處理或者備份。從前我就用過 wget 配合文字處理,把氣象股票等等資訊自動放在 bbs 的精華區之中,算是古代的 Mashup 吧。現在進入 Web 2.x 時代,情況就複雜多了。
傳統上,利用 python 抓網頁主要是使用 urllib2 之類的內建功能就可以了。自從使用 python 後,我多半是用這個方法取代 wget,畢竟可以程式處理,比較能隨自己的意思作調整,而且一個程式就解決了。當然 wget 還是有方便性,特別是你要整個站一起抓的時候。不過這種砍站作法有點暴力和不道德。
現在很多網站都有 cookie/form 這類東西,雖說 urllib2 處理 cookie 和 form 也不會太麻煩,但如果能夠有工具(有很多基於Mechanize/Mechaniod 的衍生品)能幫忙讓你不必管這些麻煩也是不錯的。更何況現在 web 2.x 時代,很多動態內容常常出現,包含 blogger 的網頁上都有很多動態內容,這些都是 dhtml/javascript 產生的,光用 urllib2 是沒辦法處理的,那怎麼辦呢?
以 python 來說,基本上有幾個解法,第一個方式,就是你手動去分析動態網頁的內容,查看實際資料的網址在什麼地方或者說動態產生的 form 或者 data 是什麼。有可以幫忙作這件事情,比方 firefox 就有 extension 可以幫你看到 xhttprequest 的網址。有時候很簡單的情況,你很容易就能找到網址,比方我之前的縮圖的那個,就是直接看內容。
第二個方式,就是用 python 來模擬 javascript的執行。這樣當然工程浩大,但是一來有現成的 javascript 處理器如 seamonkey 可用,二來可以選擇用 mechanize/DomForm來處一部分這個問題。所以這個方案其實不是那麼遙不可及。
第三種方式,就是去控制瀏覽器。你可以在瀏覽器裡面用 javascript 或 xul 來做,可以用現成的瀏覽器核心寫個瀏覽器,或者可以自動控制一個外部的瀏覽器。這些都可行,也都有人這樣做。但是如果只是平常偶而興起有個構想或者小需求,最方便的還是自動控制瀏覽器了。
這種自動機方式,windows 裡面叫做 com,python 可以利用 PAMIE 來控制 IE。mozilla 類的有兩種選擇,可以透過 xpcom 或者 jssh。xpcom 要重新編譯瀏覽器,jssh 有 extension 可以裝,但都還沒有 python module 直接支援。但在 windows 下, com 應該對於 firefox 還是可以用的。在 Linux 下面可以用 Epiphany來代替,似乎是最簡單的方式。
最近,為了方便印下 online 圖書館的書來看,所以我也需要寫個小程式來抓檔,但是不願意花太多的時間。很不幸的,這個圖書館的資料也是 ajax 產生的,所以我選擇使用 PAMIE 來做。
這裡碰到的第一個問題是 PAMIE 裡面用到很多 str(),一部分是要顯示錯誤訊息,一部分是要把html element 的屬性做個標準的編碼。但是有些 html element 的屬性名稱或者內容不會用 ascii,像是歐洲文之類的東西,所以會產生錯誤。所這個部份必須修正掉。
第二個問題,是書裡面會有插圖和 link,你下載之後有些會失效,有些圖片會防止外面的 url 盜圖。 link 的部份其實還好,用一些 regexp 處理就行,更何況我是要印出來自己看的,所以根本沒關係。圖的部份就麻煩了,總不能讓書上到處是叉燒包吧?
我們當然可以下載這些圖,然後修改圖的連結。但是很可惜, ie 的 com 似乎沒有辦法幫你存取圖的資料。也許我多翻點文件就有辦法找到適當的 api,或者我可以這部份改成使用 urllib2 來處理,但是這樣就過於麻煩,失去了一時興起寫個小程式來做這件事情的初衷。
所以我使用一個偏方來做這件事情,既然我們的麻煩來自威力強大的 web2.0,我就用威力強大的 web2.0 的方式來反擊。不過其實也只有用到 dhtml 而已。我們只要另外再開一個 IE,網址指向該線上圖書館的合法網址,然後我們改寫 innerHTML (直接用 innerHTML 太暴力了,實際上用 DOM 會比較好)。也就是說,我的第一個 IE 一頁一頁的讀取書本內容,一頁一頁的按下一頁,然後先把第二個瀏覽器內容清空,把每一頁內容寫入第二個瀏覽器中。這樣一本書翻完之後,第二個瀏覽器就有整本書的內容了,圖文並茂。
可惜 IE 並無法存下這個網頁(也許 firefox 可以,但是我沒試驗過),但是列印沒有問題。可以用 pdf printer 存成 pdf 檔,方便搜尋。我相信全選複製之後,也可以把內容貼到 word 裡面,不過我也沒有試驗過。
Categories: