python爬蟲框架之scrapy安裝與噹噹網爬蟲實戰

一、scrapy簡介

Scrapy是一個爲了爬取網站數據,提取結構性數據而編寫的應用框架。 其可以應用在數據挖掘,信息處理或存儲歷史數據等一系列的程序中。其最初是爲了頁面抓取 (更確切來說, 網絡抓取 )所設計的, 也可以應用在獲取API所返回的數據(例如 Amazon Associates Web Services ) 或者通用的網絡爬蟲。Scrapy用途廣泛,可以用於數據挖掘、監測和自動化測試。
Scrapy 使用了 Twisted異步網絡庫來處理網絡通訊。整體架構大致如下:
這裏寫圖片描述
Scrapy主要包括了以下組件:

  • 引擎(Scrapy)
    用來處理整個系統的數據流, 觸發事務(框架核心)
  • 調度器(Scheduler)
    用來接受引擎發過來的請求, 壓入隊列中, 並在引擎再次請求的時候返回. 可以想像成一個URL(抓取網頁的網址或者說是鏈接)的優先隊列, 由它來決定下一個要抓取的網址是什麼, 同時去除重複的網址。
  • 下載器(Downloader)
    用於下載網頁內容, 並將網頁內容返回給蜘蛛(Scrapy下載器是建立在twisted這個高效的異步模型上的)
  • 爬蟲(Spiders)
    爬蟲是主要幹活的, 用於從特定的網頁中提取自己需要的信息, 即所謂的實體(Item)。用戶也可以從中提取出鏈接,讓Scrapy繼續抓取下一個頁面
  • 項目管道(Pipeline)
    負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證實體的有效性、清除不需要的信息。當頁面被爬蟲解析後,將被髮送到項目管道,並經過幾個特定的次序處理數據。
  • 下載器中間件(Downloader Middlewares)
    位於Scrapy引擎和下載器之間的框架,主要是處理Scrapy引擎與下載器之間的請求及響應。
  • 爬蟲中間件(Spider Middlewares)
    介於Scrapy引擎和爬蟲之間的框架,主要工作是處理蜘蛛的響應輸入和請求輸出。
  • 調度中間件(Scheduler Middewares)
    介於Scrapy引擎和調度之間的中間件,從Scrapy引擎發送到調度的請求和響應。

Scrapy運行流程大概如下:
1. 引擎從調度器中取出一個鏈接(URL)用於接下來的抓取。
2. 引擎把URL封裝成一個請求(Request)傳給下載器。
3. 下載器把資源下載下來,並封裝成應答包(Response)。
4. 爬蟲解析Response。
5. 解析出實體(Item),則交給實體管道進行進一步的處理。
6. 解析出的是鏈接(URL),則把URL交給調度器等待抓取。

二、安裝scrapy

本文在windows平臺上進行安裝,在cmd中利用pip命令安裝,命令爲:pip install scrapy
但是提示安裝失敗,如下圖所示
這裏寫圖片描述
根據錯誤提示發現是Twisted安裝失敗導致的問題,這個庫它是用Python實現的基於事件驅動的網絡引擎框架。
嘗試用pip install Twisted進行安裝,還是出現了相同的錯誤。最後通過參考這篇博文安裝成功了Twisted,參考的博文地址爲https://blog.csdn.net/code_ac/article/details/71159244,安裝成功結果如下圖所示
這裏寫圖片描述
之後又重新運行了一次pip install scrapy這個命令,沒有錯誤提示,再用pip list命令查看了以下是否安裝上了scrapy,顯示已安裝,還可以通過輸入命令scrapy version查看一下scrapy的版本,如下圖所示,這樣scrapy就安裝好了。
這裏寫圖片描述

三、噹噹網爬蟲實戰

安裝好了scrapy,通過實戰進一步學習該框架。
首先新建一個存儲爬蟲項目的文件夾,然後在該文件夾中輸入命令scrapy startproject dangdang創建一個爬蟲項目,如下圖
這裏寫圖片描述
創建好的爬蟲項目的目錄結構如下圖所示
這裏寫圖片描述
在dangdang項目文件夾下有dangdang文件夾和scrapy.cfg文件,其中scrapy.cfg文件中主要包含的是項目的相關設置。
Spiders文件夾:我們可以在Spiders文件夾下編寫我們的爬蟲文件,裏面主要是用於分析response並提取返回的item或者是下一個URL信息,每個Spider負責處理特定的網站或一些網站。
__init__.py:項目的初始化文件。
items.py:通過文件的註釋我們瞭解到這個文件的作用是定義我們所要爬取的信息的相關屬性。Item對象是種容器,用來保存獲取到的數據。
middlewares.py:Spider中間件,在這個文件裏我們可以定義相關的方法,用以處理蜘蛛的響應輸入和請求輸出。pipelines.py:在item被Spider收集之後,就會將數據放入到item pipelines中,在這個組件是一個獨立的類,他們接收到item並通過它執行一些行爲,同時也會決定item是否能留在pipeline,或者被丟棄。
settings.py:提供了scrapy組件的方法,通過在此文件中的設置可以控制包括核心、插件、pipeline以及Spider組件。

在spiders文件夾裏創建爬蟲文件,或者可以在命令行中輸入命令scrapy genspider -t basic dangdangspider dangdang.com進行創建,命令的格式爲:scrapy genspider [-t 模板名稱] 文件名 域名
下面我們開始對http://category.dangdang.com/pg1-cp01.03.38.00.00.00.html這個網址的前100個網頁進行爬蟲實戰
首先,編寫item,代碼如下:

import scrapy

class DangdangItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    #pass
    titile = scrapy.Field()     #標題
    link = scrapy.Field()       #鏈接
    price = scrapy.Field()      #價格
    comment = scrapy.Field()    #評論數
    primecost = scrapy.Field()  #原價
    pid = scrapy.Field()        #商品id
    rebate = scrapy.Field()     #折扣
    press = scrapy.Field()      #出版社
    shop = scrapy.Field()       #店鋪名
    e_book = scrapy.Field()     #電子書
    e_price = scrapy.Field()    #電子書價格

然後編寫爬蟲程序,在dangdangspider爬蟲程序中輸入如下代碼:

import scrapy
from dangdang.items import DangdangItem
from scrapy.http import Request

class DangdangspiderSpider(scrapy.Spider):
    name = 'dangdangspider'
    allowed_domains = ['dangdang.com']
    start_urls = ['http://category.dangdang.com/pg1-cp01.03.38.00.00.00.html']

    def parse(self, response):
        #通過檢查網頁元素,發現要爬取的信息都在li標籤下
        list = response.xpath('/html/body/div[2]/div[3]/div[3]/div[9]/div[2]/ul/li')
        for li in list:
            item = DangdangItem
            item['title'] = li.xpath('div/p[1]/a/@title').extract()[0]  #此處xpath表達式不要加‘/’
            link = li.xpath('div/p[1]/a/@href').extract()[0]
            item['link'] = link.split('#')[0]          #用‘#’分割網址,去掉網址多餘的後半部分
            item['pid'] = li.xpath('@id').extract()[0]
            item['comment'] = li.xpath('div/p[2]/a/text()').extract()[0]
            item['price'] = li.xpath('div/p[6]/span[1]/text()').extract()[0].lstrip('\xa5') #需要去除‘¥’符號
            press = li.xpath('div/div/p[3]/a/text()').extract()  #出版社
            if len(press) > 0:
                item['press'] = press[0]
            else:
                item['press'] = '未知'
            shopname = li.xpath('div/p[4]/a/text()').extract()
            if len(shopname) > 0:
                item['shop'] = shopname[0]
            else:
                item['shop'] = '噹噹自營'
            item['primecost'] = li.xpath('div/p[6]/span[2]/text()').extract()[0].lstrip('\xa5') #原價
            item['rebate'] = li.xpath('div/p[6]/span[3]/text()').extract()[0]   #折扣
            e_book = li.xpath('div/div[2]/a/text()').extract()
            if len(e_book) > 0:
                item['e_book'] = e_book[0]
                item['e_price'] = li.xpath('div/div[2]/p[2]/span/text()').extract()[0].lstrip('\xa5')
            else:
                item['e_book'] = '無'
                item['e_price'] = '-'
            yield item
            for i in range(2, 101):  #爬取100頁的數據
                url = 'http://category.dangdang.com/pg' + str(i) + '-cp01.03.38.00.00.00.html'
                yield Request(url, callback = self.parse)

接下來編寫pipelines,出於調試爬蟲程序的需要,這裏的pipelines就先定義爲打印輸出在屏幕上

class DangdangPipeline(object):
    def process_item(self, item, spider):
        print(item['title'])
        print(item['link'])
        print(item['comment'])
        print(item['pid'])
        print(item['rebate'])
        print(item['price'])
        print(item['primecost'])
        print(item['press'])
        print(item['shop'])
        print(item['e_book'])
        print(item['e_price'])
        print('==============================')
        return item

然後修改settings.py文件,在22行設置爲不遵守robots.txt,修改ROBOTSTXT_OBEY = False
在67行解除pipelines的註釋,並修改爲對應的pipelines

ITEM_PIPELINES = {
   'dangdang.pipelines.DangdangPipeline': 300,
}

最後,在cmd中輸入命令 scrapy crawl dangdangspider -o dangdangbooks.csv進行爬蟲,將數據直接輸出爲csv文件
運行後出現ImportError: No module named ‘win32api’的錯誤,通過pip install pypiwin32命令安裝該庫。
再次運行爬蟲程序,成功爬到數據。
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章