【python&爬蟲】快速入門Scrapy框架

一.基本介紹

Scrapy是用純Python實現的一個開源爬蟲框架,是爲了高效地爬取網站數據,提取結構性數據而編寫的應用框架,用途非常廣泛,可用於爬蟲開發,數據挖掘,數據監測,自動化測試等領域。

二.Scrapy框架的架構

在這裏插入圖片描述
Scrapy框架包含以下組件
1.Scrapy Engine(引擎):負責Spider,Item Pipeline,DownLoader,Scheduler之間的通信,包括信號和數據的傳遞

2.Scheduler(調取器):負責接收引擎發送過來的Requests請求,並按照一定的方式進行整理排列和入隊,當引擎需要時,交還給引擎

3.Downloader(下載器):負責下載Scrapy Engine發送過來的Requests請求;並將其獲取到的Response(響應)交還給引擎,由引擎交給Spider處理

4.Spider(爬蟲):負責處理所有的Response,從中提取分析數據,獲取Item字段需要的數據,並將需要跟進的URL提交給引擎,再次進入Scheduler調取器

5.Item Pipeline(管道):負責處理Spider中獲取的Item數據,並進行後期處理(詳細分析,過濾,存儲等)

6.Downloader Middlewares(下載中間件):是一個可以自定義擴展下載功能的組件

7.Spider Middlewares(Spider中間件):是一個自定義擴展的Scrapy Engine和Spiders中間通信的功能組件 (例如:進入Spider的Response和從Spider出去的Requests)

小結:Spider的這些組件通力合作,共同完成整個爬取任務。首先從URL開始,Scheduler調度器會將其交給Downloader進行下載,下載之後會交給Spiders進行分析。Spider分析出來的結果有兩種:一種是需要進一步爬取的鏈接,例如之前分析“下一頁”鏈接,這些URL會被傳回Scheduler;另一種是需要保存的數據,它們被送到Item Pipeline,這是對數據進行後期處理(詳細分析,過濾,存儲等)。另外,在數據流動通道里還可以安裝各種中間件,進行必要的處理。

三.Scrapy安裝

pip install scrapy

四.Scrapy基本操作

1.創建Scrapy項目

scrapy startproject 項目名稱

2.在項目中創建爬蟲
需要先進入scrapy項目中

scrapy genspider 爬蟲名稱 "爬取的域名"

3.Scrapy項目目錄結構
在這裏插入圖片描述
1.Items.py 用於存放爬取下來的數據模型
2.middlewares.py 用於存放各種中間件文件
3.pipelines.py 用於將items模型存放到本地磁盤
4.setting.py 本爬蟲的一些配置信息(比如請求頭,多久發一次請求,ip代理池等)
5.scrapy.cfg 項目配置文件
6.spiders包 以後的爬蟲都是存放在這個文件裏面

五.入門案例

1.案例簡介
爬取糗事百科段子中的標題的內容
在這裏插入圖片描述
2.代碼演示
qsbk_spider.py (爬蟲)

# -*- coding: utf-8 -*-
import scrapy
# 將QsbkItem導入過來,用於封裝項目字段
from qsbk.items import QsbkItem

from scrapy.http.response.html import HtmlResponse
from scrapy.selector.unified import SelectorList

class QsbkSpiderSpider(scrapy.Spider):
    name = 'qsbk_spider'
    # allowed_domains = ['aa.com']
    start_urls = ['https://www.qiushibaike.com/text/']

    def parse(self, response):
        # contents 的數據類型是SelectorList
        contents = response.xpath('//div[@class="col1 old-style-col1"]/div')
        for content in contents:
            # content 類型:Selector
            # get方法 序列化並返回單個unicode字符串中的匹配節點。未引用百分比編碼內容。
            # title 類型:List
            title = content.xpath('./div[@class="author clearfix"]/a[2]/h2/text()').get().strip()
            # getall()返回匹配的所有節點,並以列表的形式返回
            detail = content.xpath('.//div[@class="content"]//text()').getall()
            detail = "".join(detail).strip()

            # 創建一個字典,用於返回爬取結果
            item = QsbkItem(title = title,detail = detail)
            # item = {"title":title,"detail":detail}
            # yield可以將函數變成生成器,可以將結果一個一個的返回到爬蟲引擎
            yield item

        # 找到下一頁的url
        next_url = response.xpath('//ul[@class="pagination"]/li[last()]/a/@href').get()
        # 判斷是否找到最後一頁
        if not next_url:
            return
        else:
            # 拼接出完整的url鏈接
            url1 = "https://www.qiushibaike.com" + next_url
            # 請求下一頁
            yield scrapy.Request(url1,callback=self.parse)

item.py

import scrapy

class QsbkItem(scrapy.Item):
    # 此處用於定義項目的字段,使得代碼更加規範
    # 固定寫法
    title = scrapy.Field()
    detail = scrapy.Field()

pipelines.py (存儲數據)
將爬取下來的數據保存成json文件格式有三種方式
方式一:直接存入json文件

import json
class QsbkPipeline(object):
    def __init__(self):
        # 構造方法用於打開一個文件,也可以在open_spider方法中打開文件
        self.file = open("./糗事段子.json","w",encoding="utf-8")

    def open_spider(self,spider):
        # 爬蟲開始時會執行這行代碼
        print("爬蟲開始")

    # 這個方法用於處理爬蟲引擎返回過來的結果
    def process_item(self, item, spider):
        # 因爲item被QsbkItem類包裝,所有要先轉換成字典,才能被dumps成json格式
        # 將返回過來的數據 dumps成json格式
        # ensure_ascii = False表示不適用ascii碼,即可正常顯示中文
        item_json = json.dumps(dict(item),ensure_ascii=False)
        self.file.write(item_json+"\n")
        return item


    def close_spider(self,spider):
        # 爬蟲結束時會執行這行代碼
        print("爬蟲結束")

方式二:使用JsonItemExporter存儲

# 數據先存儲到內存中,爬蟲結束後,統一存儲到文件
from scrapy.exporters import JsonItemExporter
class QsbkPipeline(object):
    def __init__(self):
        # 構造方法用於打開一個文件,也可以在open_spider方法中打開文件
        # 因爲這個模塊是以二進制的方式寫入,所以文件需要用二進制的方式打開
        self.file = open("./糗事段子.json","wb")
        # 創建一個導出對象
        self.exports = JsonItemExporter(self.file,ensure_ascii=False,encoding="utf-8")
        # 打開到處對象
        self.exports.start_exporting()

    def open_spider(self,spider):
        # 爬蟲開始時會執行這行代碼
        print("爬蟲開始")

    # 這個方法用於處理爬蟲引擎返回過來的結果
    def process_item(self, item, spider):
        # 將數據存入
        # 用這種方式就不需要將item轉換成字典了
        # 存儲格式爲列表,列表中的每一項時字典
        # 這種方式會先把數據統一存儲導內存中,然後最後統一存儲導磁盤,比較費內存
        self.exports.export_item(item)
        return item

    def close_spider(self,spider):
        # 關閉exporters對象
        self.exports.finish_exporting()
        # 爬蟲結束時會執行這行代碼
        print("爬蟲結束")

方式三:使用JsonLinesItemExporter存儲

# 每行每行的寫入文件,跟第一種方式存儲方式一樣
from scrapy.exporters import JsonLinesItemExporter

class QsbkPipeline(object):
    def __init__(self):
        # 構造方法用於打開一個文件,也可以在open_spider方法中打開文件
        # 也需要使用二進制的方式打開
        self.file = open("./糗事段子.json", "wb")
        self.exporters = JsonLinesItemExporter(self.file, ensure_ascii=False, encoding="utf-8")

    def open_spider(self, spider):
        # 爬蟲開始時會執行這行代碼
        print("爬蟲開始")

    # 這個方法用於處理爬蟲引擎返回過來的結果
    def process_item(self, item, spider):
        # 寫入數據
        self.exporters.export_item(item)
        return item


    def close_spider(self, spider):
        # 關閉文件
        self.file.close()
        # 爬蟲結束時會執行這行代碼
        print("爬蟲結束")

這三種存儲方式小結:
1.打開文件,將item轉換成json格式,然後一個一個寫入到文件(常規方式)
2.使用scrapy自帶類存儲JsonItemExporter和JsonLinesItemExporters兩種方式
(1)JsonItemExporters:這個是每次把數據添加到內存中,最後統一寫入到磁盤。好處是:存儲的是一個滿足json規則的數據,壞處是,如果數據大時,比較耗內存

(2)JsonLinesItemExporters:這個是每次調用export_item時,就把這個item存儲到磁盤中。壞處時每個字典就是一行,整個文件不是滿足json格式的文件。好處是每次處理數據的時候就直接寫入到了磁盤,不會耗內存,比較安全

六.案例小結

1.response是一個scrapy.http.response.html.HtmlResponse對象,可以執行xpath css語法來提取數據

2.提取出來的數據是一個Selector或者SelectorList對象,如果想獲取其中的字符串,那麼應該執行get或者getall方法

3.getall方法,用於獲取selector中所有的文本,返回一個列表

4.get方法,獲取Selector中第一個方法,返回一個str類型

5.如果數據解析回來,要傳給pipeline處理,那麼可以使用yield來返回,也可以蒐集所有的item,最後存入列表統一用return返回

6.item 建議在Items.py中定義好模型,以後不要使用字典返回

7.pipeline,這個專門用於保存數據的,其中有三個方法比較常用:
(1)open_spider(self,spider) 爬蟲被打開時會被調用
(2)process_spider(self,item,spider) 爬蟲將item轉過來時會被調用
(3)close_spider(self,spider) 爬蟲結束時會被調用
注意:要使用pipeline, 需要在setting.py中激活pipeline,並設置ITEM_PIPELINES

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