網頁爬蟲--scrapy入門

本篇從實際出發,展現如何用網頁爬蟲。並介紹一個流行的爬蟲框架~html


1. 網頁爬蟲的過程

所謂網頁爬蟲,就是模擬瀏覽器的行爲訪問網站,從而得到網頁信息的程序。正由於是程序,因此得到網頁的速度能夠輕易超過單身多年的手速:)。一般適用於須要大量網頁信息的場合。python

爬取網頁的流程爲:訪問初始url -> 得到返回的網頁,從這個網頁中獲得新的url並放入待爬隊列 -> 訪問新的url -> ...依次循環。總體上來看就是一個廣度優先的過程,固然,新的url也不必定非要從返回的網頁中得到。算法

一個簡單的網頁爬蟲應該包括如下部分:網頁爬蟲

  1. 一個url隊列。咱們的爬蟲從這個隊列中讀取url,並將新的url放入這個隊列。這裏最重要的是判重。簡單的哈希就能達到判重的目的,可是爲了節約空間(url的數量每每不少),通常使用bloomfilter的思想。bloomfilter與普通的哈希算法最大的不一樣就是bloomfilter只須要一個bit來表示某個元素是否存在,因此能節約空間。bloomfilter有一個小缺點,即準確率並非百分百:判斷一個元素是否是已經存在時,已有的有很小的可能會判斷爲不存在,可是沒有的元素必定會判斷爲不存在。
  2. 網頁爬取模塊。須要能模擬瀏覽器發送請求。
  3. 網頁分析模塊。爬下來的是網頁源碼,能夠用正則或者其餘方法提取咱們須要的信息。
  4. 新的url生成模塊。生成新的url,放入隊列。

那麼,最簡單的爬蟲就能夠這麼寫:瀏覽器

import Queue

start_url = "http://www.cnblogs.com/rubinorth"
url_queue = Queue.Queue()  # url隊列
url_queue.put(start_url) 

bloomfilter.put(start_url)
#### 一直循環到隊列爲空 ####
while(True):
    if url_queue.size() > 0:
        current_url = url_queue.get()  # 隊首的url
        page = crawl(current_url)  # crawl爲網頁爬取模塊,page是爬到的網頁源代碼
        next_urls = deal_page(page)  # deal_page爲網頁分析模塊,next_urls是新的一些url
        
        for next_url in next_urls: 
            if not bloomfilter.has(next_url):  # 判重     
                bloomfilter.put(next_url)
                url_queue.put(next_url)
    else:
        break

2. 爲何選用scrapy

scrapy是目前一個比較流行的爬蟲框架,其基本原理與上面的爬蟲是同樣的,可是它提供了不少便利的功能。cookie

首先,先簡要介紹一下scrapy各個模塊之間的關係和整個框架運行的流程。是時候祭出那張scrapy的經典圖了:
scrapy
從這張圖上看,scrapy包含了如下模塊:python爬蟲

  1. scrapy engine,主引擎。在處理數據流時負責管理整個系統,同時各類事件的觸發也由其負責。
  2. spider,即咱們的爬蟲。主要的爬蟲代碼都在這部分中,包括髮起請求,處理返回的網頁等等。
  3. spider middleware,spider中間件。中間件的一種,主要工做對spider發送的request作一些處理。
  4. scheduler,調度器。上面說到的url隊列就是調度器在管理,一方面接收spider發送的request請求,放入隊列中;另外一方面會從隊首取出request交由downloader去下載網頁。
  5. downloader,下載器。將網頁的html源碼下載下來供以後的網頁分析和信息提取。
  6. downloader middleware,下載器中間件。中間件的一種,在下在網頁以前和以後都會運行,能夠用來設置發送請求的header,cookies,代理ip以及處理一些錯誤返回的狀況。
  7. item pipeline, 管道。一個網頁被爬取下來並解析以後,其後續的信息存儲之類的工做在pipeline中進行。固然也能夠直接在spider中完成這些工做,但在pipeline中完成則顯得整個項目結構清晰。

上面列出的裏面spider,pipeline須要本身寫,兩種middleware須要的話能夠本身添加本身寫的。框架

光介紹給人感受比較空洞,那下面就讓咱們來使用scrapy實現一個簡單的爬蟲吧。dom


3. scrapy實現爬蟲

scrapy createproject cnblog_project

使用上面的命令建立一個scrapy工程以後,首先咱們要寫的是spider。scrapy

class CnblogSpider(Spider):
    name = 'cnblog_spider'  # 爬蟲名字
    allowed_domain = ['cnblogs.com']  # 容許的domain

    def __init__(self):
        self.start_urls = ['http://www.cnblogs.com/rubinorth']

    def start_requests(self):
        return [Request(url, callback=self.parse_page) for url in self.start_urls]

    # 分析爬取的頁面並構造下一個頁面的請求
    def parse_page(self, response):
        logging.info("parse : " + response.url)

        sel = Selector(response)
        item = CnblogItem()

        # 提取頁面內容
        item['name'] = sel.xpath("//a[@id='Header1_HeaderTitle']/text()").extract()[0]
        yield item
        # 下一個頁面的請求
        new_url = get_new_url(response.body)  # 根據源碼分析出新的連接,需本身實現
        yield Request(new_url, callback=self.parse_page)

上面是一個簡單的爬蟲,start_urls是初始的url集合(上面只有一個),start_requests則根據start_urls構造Request,並交給調度器。parse_page中,response是返回的頁面的源碼;CnblogItem是scrapy提供的item組件,方便結構化地提取源碼中的數據,而yield item則會將這個item交給管道;yield Request(new_url, callback=self.parse_page)則會發送一個新的Request,發起下一輪的爬取。
items.py中只要這麼寫:

class CnblogItem(scrapy.Item):
    name = scrapy.Field()

接着,咱們須要寫pipelines.py

class CnblogPipeline(object):
    def process_item(self, item, spider):
        print item['name']
        return item

每一個pipeline都必須有process_item這個方法。上面咱們只是簡單地打印出了name。return item是考慮到可能有多個pipeline(return了以後可讓其餘pipeline處理)。
最後,只須要修改settings.py便可:

...
ITEM_PIPELINES = {
   'yelp_project.pipelines.CnblogPipeline': 304,
}
...

須要在setting中打開本身的pipeline。
好了,一個簡單的爬蟲就這麼寫完了。注意咱們並無用到中間件,也不須要寫本身的中間件。
最後, 命令行運行:

scrapy crawl cnblog_spider

參考資料

如何入門python爬蟲

轉載請註明出處:http://www.cnblogs.com/rubinorth/

相關文章
相關標籤/搜索