在上兩篇教程中,我們學習了怎麼從 HTML 中提取資訊,也學習了怎麼處理一些請求複雜的頁面。但是有一些頁面,它實在太複雜了,無論是分析 API 請求的地址,還是渲染時進行了加密,讓直接抓取請求非常麻煩。這時候就是 PhantomJS 大顯身手的時候了。
在使用 PhantomJS 之前,你需要安裝它(安裝文件)。當你安裝了之後,在執行 all
模式的 pyspider 時就會自動啟用了。當然,你也可以在 demo.pyspider.org 上嘗試。
使用 PhantomJS
當 pyspider 連上 PhantomJS 代理後,你就能通過在 self.crawl
中新增 fetch_type='js'
的引數,開啟使用 PhantomJS 抓取。例如,在教程二中,我們嘗試抓取的 http://movie.douban.com/explore 就可以通過 PhantomJS 直接抓取:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Handler(BaseHandler): def on_start(self): self.crawl('http://movie.douban.com/explore', fetch_type='js', callback=self.phantomjs_parser) def phantomjs_parser(self, response): return [{ "title": "".join( s for s in x('p').contents() if isinstance(s, basestring) ).strip(), "rate": x('p strong').text(), "url": x.attr.href, } for x in response.doc('a.item').items()] |
- 我在這裡使用了一些 PyQuery 的 API,你可以在 PyQuery complete API 獲得完整的 API 手冊。
在頁面上執行自定義指令碼
你會發現,在上面我們使用 PhantomJS 抓取的豆瓣熱門電影只有 20 條。當你點選『載入更多』時,能獲得更多的熱門電影。為了獲得更多的電影,我們可以使用 self.crawl
的 js_script
引數,在頁面上執行一段指令碼,點選載入更多:
1 2 3 4 5 6 7 |
def on_start(self): self.crawl('http://movie.douban.com/explore#more', fetch_type='js', js_script=""" function() { setTimeout("$('.more').click()", 1000); }""", callback=self.phantomjs_parser) |
- 這個指令碼預設在頁面載入結束後執行,你可以通過
js_run_at
引數 修改這個行為- 由於是 AJAX 非同步載入的,在頁面載入完成時,第一頁的電影可能還沒有載入完,所以我們用
setTimeout
延遲 1 秒執行。- 你可以間隔一定時間,多次點選,這樣可以載入更多頁。
- 由於相同 URL (實際是相同 taskid) 的任務會被去重,所以這裡為 URL 加了一個
#more
上面兩個例子,都可以在 http://demo.pyspider.org/debug/tutorial_douban_explore 中找到。