網絡爬蟲(web crawler)又稱爲網絡蜘蛛(web spider)是一段計算機程序,它從互聯網上按照必定的邏輯和算法抓取和下載互聯網的網頁,是搜索引擎的一個重要組成部分。通常的爬蟲從一部分start url開始,按照必定的策略開始爬取,爬取到的新的url在放入到爬取隊列之中,而後進行新一輪的爬取,直到抓取完畢爲止。 php
咱們看一下crawler通常會遇到什麼樣的問題吧: html
海量網頁的存在就意味着在必定時間以內,抓取只能的抓取其中的一部分,所以須要定義清楚抓取的優先級;網頁更新的頻繁,也就意味着須要抓取最新的網頁和保證連接的有效性,所以一個更有可能帶來新網頁的列表頁顯得尤其重要;對於新聞網站,新的網站通常出如今首頁,或者在指定的分類網頁,可是對於淘寶來講,商品的更新就很難估計了;動態網頁怎麼辦呢?如今的網頁大都有JS和AJAX,抓取已經不是簡單的執行wget下載,現代的網頁結構須要咱們的爬蟲更加智能,須要更靈活的應對網頁的各類狀況。 java
所以,對一個通用的爬蟲個,咱們要定義 python
抓取策略 web
使用URL的正則特徵是一個簡單但卻很高效的模式;對於定向抓取,通常的網站的URL有必定的特徵,好比可能僅僅關心 .html, .htm, .asp, .aspx, .php, .jsp, .jspx類型的網頁;或者是若是能夠獲得目標網站的正則,則能夠大大的下降抓取的數量;又或者咱們無需關心某一類網頁,好比咱們不抓取bbs.taobao.com下面的內容;僅僅須要抓取淘寶的商品頁面(http://item.taobao.com/item.htm?id=\d+ )。經過URL的正則能極大的下降抓取數量; 算法
也能夠經過網頁的文本特徵來肯定;不過要複雜得多了,通常須要必定數量已知頁面的訓練集合,而後提取頁面的文本特徵,而後經過向量空間模型或者其其餘基於主題詞提取的模型計算目標網頁和訓練集網頁的距離,決定是不是目標網頁。 瀏覽器
更新策略 網絡
Freshness:表示抓取到的網頁是否已經被修改 多線程
Age:表示抓取的網頁過時的時間 架構
對於更新來講,目標是讓平均age時間越小,freshness越高;通常的更新策略有兩種:按期批量更新和按更新週期更新;按期批量更新指對一批URL,按照失效時間按期去刷新,按週期更新指的是按照頁面更新變化頻率而修正是更新頻率,通常來講,更新越頻繁的網頁更新也就越快。
抽取策略:
XPATH是一個簡單直觀,可是頗有效的一個方案,XPATH能精準的定位網頁的任意一個位置,意味着咱們能夠很精準的抽取頁面上的任意位置,當面臨不少網站的時候,固然配置XPATH就是一個很艱鉅的任務,也許存在一個自適應的XPATH識別的方法。
JS和AJAX
在java下面,HtmlUnit是一個不錯的解決方案,HtmlUnit是Junit 的擴展測試框架之一,該框架模擬瀏覽器的行爲,開發者可使用其提供的API對頁面的元素進行操做,套用官方網站的話HtmlUnit「是Java程序的瀏覽器」。HtmlUnit支持HTTP,HTTPS,COOKIE,表單的POST和GET方法,可以對HTML文檔進行包裝,頁面的各類元素均可以被看成對象進行調用,另外對JavaScript的支持也比較好。通常來講,HtmlUnit是在java環境下解決JS的很好的選擇
WebKit包含一個網頁引擎WebCore和一個腳本引擎JavaScriptCore,它們分別對應的是KDE的KHTML和KJS;目前比較主流的瀏覽器Google Chrome和Apple的safari,都是基於WebKit的內核寫的。使用瀏覽器做爲抓取能更好的模擬用戶瀏覽的行爲,可以自然的解決JS和AJAX等問題,問題可能就是性能是一個瓶頸,
抓取頻率
同時開啓N個線程抓取一個網站,相信很快就會被對方網站封掉;所以抓取的頻率也很重要;抓取網站同時不對對方網站形成壓力;在robot.txt協議裏面定義Crawl-delay來肯定抓取的頻率也是一種網站的通用的作法,對於通常的抓取而言,10到20秒抓取一次是一個比較保險的頻率,也有提出10*t的抓取間隔(t是download時間)比較合理
定向抓取的框架
通用抓取架構,以下圖
多線程下載模塊(Multi-threaded downloader)
該模塊通常包含:
調度模塊(schedule)
調度模塊是抓取系統的核心,調度模塊從url隊列裏面選擇一批url喂到下載模塊下載;其中會涉及到
實例:使用開源的scrapy爬蟲抓取B2C站點的商品
Scrapy(http://scrapy.org/)是基於Twisted的異步處理框架,純python實現的爬蟲框架,用戶只須要定製開發幾個模塊就能夠輕鬆的實現一個爬蟲,用來抓取網頁內容以及各類圖片,很是之方便,如今咱們以scrapy爲例子,簡單配置一個抓取商品的例子。
Scrapy的安裝請參考 http://doc.scrapy.org/intro/install.html#intro-install
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
fromscrapy.selectorimportHtmlXPathSelector
fromscrapy.spiderimportBaseSpider
fromscrapy.contrib.linkextractors.sgmlimportSgmlLinkExtractor
fromscrapy.utils.urlimporturljoin_rfc
fromscrapy.httpimportRequest
classMySpider(BaseSpider):
name='test'
allowed_domains=['xxxx.com']
start_urls=[
]
download_delay=10
defparse(self, response):
forlinkinSgmlLinkExtractor(allow=" product.htm\?id=\d+").extract_links(response):
yieldRequest(link.url,callback=self.parse_detail)
hxs=HtmlXPathSelector(response)
forurlinhxs.select('//a/
@href ').extract():
url= self._urljoin(response,url)
#print url
yieldRequest(url, callback=self.parse)
defparse_detail(self, response):
hxs=HtmlXPathSelector(response)
what_u_want=hxs.select("/xpath/text()").extract()[0]
print'url=',response.url, what_u_want.strip()
return
def_urljoin(self, response, url):
"""Helper to convert relative urls to absolute"""
returnurljoin_rfc(response.url, url, response.encoding)
|
最後,在工程目錄裏面執行 scrapy crawl mycrawler
簡單幾步,咱們就能夠抓取獲得一個站點想要的頁面了,而且能夠抽取指定xpath的內容。
一個簡單的定向爬蟲就搭建起來了,關鍵是一個可以大規模的分佈式的爬蟲多是一個挑戰,後續再進一步介紹如何在分佈式環境進行大規模的抓取,以及抓取遇到的一些更爲棘手的問題