雖然之前寫過 如何抓取WEB頁面 和 如何從 WEB 頁面中提取信息。可是感受仍是須要一篇 step by step 的教程,否則沒有一個整體的認識。不過,沒想到這個教程竟然會變成一篇譯文,在這個爬蟲教程系列文章中,會以實際的例子,由淺入深討論爬取(抓取和解析)的一些關鍵問題。css
在 教程一 中,咱們將要爬取的網站是豆瓣電影:http://movie.douban.com/html
你能夠在: http://demo.pyspider.org/debug/tutorial_douban_movie 得到完整的代碼,和進行測試。前端
因爲教程是基於 pyspider 的,你能夠安裝一個 pyspider(Quickstart,也能夠直接使用 pyspider 的 demo 環境: http://demo.pyspider.org/。python
你還應該至少對萬維網是什麼有一個簡單的認識:程序員
因此,爬網頁實際上就是:web
既然咱們要爬全部的電影,首先咱們須要抓一個電影列表,一個好的列表應該:chrome
咱們在 http://movie.douban.com/ 掃了一遍,發現並無一個列表能包含全部電影,只能退而求其次,經過抓取分類下的全部的標籤列表頁,來遍歷全部的電影: http://movie.douban.com/tag/app
在 pyspider 的 dashboard 的右下角,點擊 "Create" 按鈕ide
替換 on_start
函數的 self.crawl
的 URL:函數
python@every(minutes=24 * 60) def on_start(self): self.crawl('http://movie.douban.com/tag/', callback=self.index_page)
self.crawl
告訴 pyspider 抓取指定頁面,而後使用callback
函數對結果進行解析。@every
修飾器,表示on_start
天天會執行一次,這樣就能抓到最新的電影了。
點擊綠色的 run
執行,你會看到 follows
上面有一個紅色的 1,切換到 follows
面板,點擊綠色的播放按鈕:
在 tag 列表頁 中,咱們須要提取出全部的 電影列表頁 的 URL。你可能已經發現了,sample handler 已經提取了很是多大的 URL,全部,一種可行的提取列表頁 URL 的方法就是用正則從中過濾出來:
pythonimport re ... @config(age=10 * 24 * 60 * 60) def index_page(self, response): for each in response.doc('a[href^="http"]').items(): if re.match("http://movie.douban.com/tag/\w+", each.attr.href, re.U): self.crawl(each.attr.href, callback=self.list_page)
- 因爲 電影列表頁和 tag列表頁長的並不同,在這裏新建了一個
callback
爲self.list_page
@config(age=10 * 24 * 60 * 60)
在這表示咱們認爲 10 天內頁面有效,不會再次進行更新抓取
因爲 pyspider 是純 Python 環境,你可使用 Python 強大的內置庫,或者你熟悉的第三方庫對頁面進行解析。不過更推薦使用 CSS選擇器。
再次點擊 run
讓咱們進入一個電影列表頁(list_page
)。在這個頁面中咱們須要提取:
CSS選擇器,顧名思義,是 CSS 用來定位須要設置樣式的元素 所使用的表達式。既然前端程序員都使用 CSS選擇器 爲頁面上的不一樣元素設置樣式,咱們也能夠經過它定位須要的元素。你能夠在 CSS 選擇器參考手冊 這裏學習更多的 CSS選擇器 語法。
在 pyspider 中,內置了 response.doc
的 PyQuery 對象,讓你可使用相似 jQuery 的語法操做 DOM 元素。你能夠在 PyQuery 的頁面上找到完整的文檔。
在 pyspider 中,還內置了一個 CSS Selector Helper
,當你點擊頁面上的元素的時候,能夠幫你生成它的 CSS選擇器 表達式。你能夠點擊 Enable CSS selector helper
按鈕,而後切換到 web
頁面:
開啓後,鼠標放在元素上,會被黃色高亮,點擊後,全部擁有相同 CSS選擇器 表達式的元素會被高亮。表達式會被插入到 python 代碼當前光標位置。建立下面的代碼,將光標停留在單引號中間:
pythondef list_page(self, response): for each in response.doc('').items():
點擊一個電影的連接,CSS選擇器 表達式將會插入到你的代碼中,如此重複,插入翻頁的連接:
pythondef list_page(self, response): for each in response.doc('HTML>BODY>DIV#wrapper>DIV#content>DIV.grid-16-8.clearfix>DIV.article>DIV>TABLE TR.item>TD>DIV.pl2>A').items(): self.crawl(each.attr.href, callback=self.detail_page) # 翻頁 for each in response.doc('HTML>BODY>DIV#wrapper>DIV#content>DIV.grid-16-8.clearfix>DIV.article>DIV.paginator>A').items(): self.crawl(each.attr.href, callback=self.list_page)
- 翻頁是一個到本身的
callback
回調
再次點擊 run
,follow 到詳情頁。使用 css selector helper
分別添加電影標題,打分和導演:
pythondef detail_page(self, response): return { "url": response.url, "title": response.doc('HTML>BODY>DIV#wrapper>DIV#content>H1>SPAN').text(), "rating": response.doc('HTML>BODY>DIV#wrapper>DIV#content>DIV.grid-16-8.clearfix>DIV.article>DIV.indent.clearfix>DIV.subjectwrap.clearfix>DIV#interest_sectl>DIV.rating_wrap.clearbox>P.rating_self.clearfix>STRONG.ll.rating_num').text(), "導演": [x.text() for x in response.doc('a[rel="v:directedBy"]').items()], }
注意,你會發現 css selector helper
並非老是能提取到合適的 CSS選擇器 表達式。你能夠在 Chrome Dev Tools 的幫助下,寫一個合適的表達式:
右鍵點擊須要提取的元素,點擊審查元素。你並不須要像自動生成的表達式那樣寫出全部的祖先節點,只要寫出那些能區分你不須要的元素的關鍵節點的屬性就能夠了。不過這須要抓取和網頁前端的經驗。因此,學習抓取的最好方法就是學會這個頁面/網站是怎麼寫的。
你也能夠在 Chrome Dev Tools 的 Javascript Console 中,使用 $$(a[rel="v:directedBy"])
測試 CSS Selector。
run
單步調試你的代碼,對於用一個 callback
最好使用多個頁面類型進行測試。而後保存。 status
修改成 DEBUG
或 RUNNING
run
按鈕
原文:http://blog.binux.me/2015/01/pyspider-tutorial-level-1-html-and-css-selector/ (樣式比原文還好看,鬧哪樣啊)