小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

從原理到實(shí)戰(zhàn),一份詳實(shí)的 Scrapy 爬蟲教程,值得收藏

 閑野之家 2022-03-21

大家好,歡迎來到 Crossin的編程教室 !

之前分享了很多 requests 、selenium 的 Python 爬蟲文章,本文將從原理到實(shí)戰(zhàn)帶領(lǐng)大家入門另一個(gè)強(qiáng)大的框架 Scrapy。如果對Scrapy感興趣的話,不妨跟隨本文動手做一遍!

圖片

一、Scrapy框架簡介

Scrapy是:由Python語言開發(fā)的一個(gè)快速、高層次的屏幕抓取和web抓取框架,用于抓取web站點(diǎn)并從頁面中提取結(jié)構(gòu)化的數(shù)據(jù),只需要實(shí)現(xiàn)少量的代碼,就能夠快速的抓取。

二、運(yùn)行原理

Scrapy框架的運(yùn)行原理看下面一張圖就夠了(事實(shí)上原理是比較復(fù)雜的,也不是三言兩語能夠說清楚的,因此感興趣的讀者可以進(jìn)一步閱讀更多的相關(guān)文章來了解,本文不做過多講解圖片

Scrapy主要包括了以下組件:

  • 引擎(Scrapy Engine)
  • Item 項(xiàng)目
  • 調(diào)度器(Scheduler)
  • 下載器(Downloader)
  • 爬蟲(Spiders)
  • 項(xiàng)目管道(Pipeline)
  • 下載器中間件(Downloader Middlewares)
  • 爬蟲中間件(Spider Middlewares)
  • 調(diào)度中間件(Scheduler Middewares)

三. 入門

3.1安裝

第一種:在命令行模式下使用pip命令即可安裝:

$ pip install scrapy

第二種:首先下載,然后再安裝:

$ pip download scrapy -d ./
# 通過指定國內(nèi)鏡像源下載 
$pip download  -i https://pypi.tuna./simple scrapy -d ./

進(jìn)入下載目錄后執(zhí)行下面命令安裝:

$ pip install Scrapy-1.5.0-py2.py3-none-any.whl

3.2使用

使用大概分為下面四步 1 創(chuàng)建一個(gè)scrapy項(xiàng)目

scrapy startproject mySpider

2 生成一個(gè)爬蟲

scrapy genspider demo 'demo.cn'

3 提取數(shù)據(jù)

完善spider 使用xpath等

4 保存數(shù)據(jù)

pipeline中保存數(shù)據(jù)

3.3 程序運(yùn)行

在命令中運(yùn)行爬蟲

scrapy crawl qb     # qb爬蟲的名字

在pycharm中運(yùn)行爬蟲

from scrapy import cmdline
cmdline.execute('scrapy crawl qb'.split())

四、基本步驟

Scrapy 爬蟲框架的具體使用步驟如下:

  1. 選擇目標(biāo)網(wǎng)站
  2. 定義要抓取的數(shù)據(jù)(通過Scrapy Items來完成的)
  3. 編寫提取數(shù)據(jù)的spider
  4. 執(zhí)行spider,獲取數(shù)據(jù)
  5. 數(shù)據(jù)存儲

五. 目錄文件說明

當(dāng)我們創(chuàng)建了一個(gè)scrapy項(xiàng)目后,繼續(xù)創(chuàng)建了一個(gè)spider,目錄結(jié)構(gòu)是這樣的:

圖片

下面來簡單介紹一下各個(gè)主要文件的作用:

scrapy.cfg :項(xiàng)目的配置文件

mySpider/ :項(xiàng)目的Python模塊,將會從這里引用代碼

mySpider/items.py :項(xiàng)目的目標(biāo)文件

mySpider/pipelines.py :項(xiàng)目的管道文件

mySpider/settings.py :項(xiàng)目的設(shè)置文件

mySpider/spiders/ :存儲爬蟲代碼目錄

5.1 scrapy.cfg文件

項(xiàng)目配置文件。這個(gè)是文件的內(nèi)容:

# Automatically created by: scrapy startproject
#
# For more information about the [deploy] section see:
# https://scrapyd./en/latest/deploy.html

[settings]
default = mySpider.settings

[deploy]
#url = http://localhost:6800/
project = mySpider

5.2 mySpider**/**

項(xiàng)目的Python模塊,將會從這里引用代碼

5.3 mySpider/items.py

項(xiàng)目的目標(biāo)文件

# Define here the models for your scraped items
#
# See documentation in:
# https://docs./en/latest/topics/items.html

import scrapy

class MyspiderItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass

定義scrapy items的模塊,示例: name = scrapy.Field()

5.4 mySpider/pipelines.py

項(xiàng)目的管道文件

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs./en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter


class MyspiderPipeline:
    def process_item(self, item, spider):
        return item

這個(gè)文件也就是我們說的管道,當(dāng)Item在Spider中被收集之后,它將會被傳遞到Item Pipeline(管道),這些Item Pipeline組件按定義的順序處理Item。每個(gè)Item Pipeline都是實(shí)現(xiàn)了簡單方法的Python類,比如決定此Item是丟棄而存儲。以下是item pipeline的一些典型應(yīng)用:

  • 驗(yàn)證爬取的數(shù)據(jù)(檢查item包含某些字段,比如說name字段)
  • 查重(并丟棄)
  • 將爬取結(jié)果保存到文件或者數(shù)據(jù)庫中

5.5 mySpider/settings.py

項(xiàng)目的設(shè)置文件

# Scrapy settings for mySpider project
...

BOT_NAME = 'mySpider' # scrapy項(xiàng)目名

SPIDER_MODULES = ['mySpider.spiders']
NEWSPIDER_MODULE = 'mySpider.spiders'
.......

# Obey robots.txt rules
ROBOTSTXT_OBEY = False # 是否遵守協(xié)議,一般給位false,但是創(chuàng)建完項(xiàng)目是是True,我們把它改為False

# Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32 # 最大并發(fā)量 默認(rèn)16
......
#DOWNLOAD_DELAY = 3 # 下載延遲 3秒

# Override the default request headers: # 請求報(bào)頭,我們打開
DEFAULT_REQUEST_HEADERS = {
  'Accept''text/html,application/xhtml xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language''en',
}
# 爬蟲中間件
#SPIDER_MIDDLEWARES = {
#    'mySpider.middlewares.MyspiderSpiderMiddleware': 543,
#}

# 下載中間件
#DOWNLOADER_MIDDLEWARES = {
#    'mySpider.middlewares.MyspiderDownloaderMiddleware': 543,
#}
......
# Configure item pipelines
# See https://docs./en/latest/topics/item-pipeline.html
#ITEM_PIPELINES = {
#    'mySpider.pipelines.MyspiderPipeline': 300, # 管道
#}
.......

省略號省略代碼,一般重要點(diǎn),給了注釋

6.mySpider/spiders/ :存儲爬蟲代碼目錄

import scrapy

class DbSpider(scrapy.Spider):
    name = 'db'
    allowed_domains = ['douban.com'# 可以修改
    start_urls = ['http://douban.com/'# 開始的url也可以修改

    def parse(self, response):
        # pass

六. Scrapy shell

Scrapy終端是一個(gè)交互終端,我們可以在未啟動spider的情況下嘗試及調(diào)試代碼,也可以用來測試XPath或CSS表達(dá)式,查看他們的工作方式,方便我們爬取的網(wǎng)頁中提取的數(shù)據(jù),但是一般使用的不多。感興趣的查看官方文檔:

官方文檔

http://scrapy-chs./zh_CN/latest/topics/shell.html

Scrapy Shell根據(jù)下載的頁面會自動創(chuàng)建一些方便使用的對象,例如 Response 對象,以及 Selector 對象 (對HTML及XML內(nèi)容)。

  • 當(dāng)shell載入后,將得到一個(gè)包含response數(shù)據(jù)的本地 response 變量,輸入 response.body將輸出response的包體,輸出 response.headers 可以看到response的包頭。
  • 輸入 response.selector 時(shí), 將獲取到一個(gè)response 初始化的類 Selector 的對象,此時(shí)可以通過使用 response.selector.xpath()response.selector.css() 來對 response 進(jìn)行查詢。
  • Scrapy也提供了一些快捷方式, 例如 response.xpath()response.css()同樣可以生效(如之前的案例)。

Selectors選擇器

Scrapy Selectors 內(nèi)置 XPathCSS Selector 表達(dá)式機(jī)制

Selector有四個(gè)基本的方法,最常用的還是xpath:

  • xpath(): 傳入xpath表達(dá)式,返回該表達(dá)式所對應(yīng)的所有節(jié)點(diǎn)的selector list列表
  • extract(): 序列化該節(jié)點(diǎn)為字符串并返回list
  • css(): 傳入CSS表達(dá)式,返回該表達(dá)式所對應(yīng)的所有節(jié)點(diǎn)的selector list列表,語法同 BeautifulSoup4
  • re(): 根據(jù)傳入的正則表達(dá)式對數(shù)據(jù)進(jìn)行提取,返回字符串list列表

七、案例實(shí)戰(zhàn)

本節(jié),我將使用Scrapy爬取站酷數(shù)據(jù)作為示例

圖片

7.1 案例說明

既然已經(jīng)初步了解了scrapy的工作流程以及原理,我們來做一個(gè)入門的小案例,爬取站酷首頁推薦的item信息。如下圖所示,一個(gè)小方框就是一個(gè)item信息。我們要提取每一個(gè)item的六個(gè)組成部分:

  1. imgLink(封面圖片鏈接);
  2. title(標(biāo)題);
  3. types(類型);
  4. vistor(人氣);
  5. comment(評論數(shù));
  6. likes(推薦人數(shù))圖片

然后只是一個(gè)頁面的item,我們還要通過翻頁實(shí)現(xiàn)批量數(shù)據(jù)采集。

7.2 文件配置

目錄結(jié)構(gòu)

在上一篇中我們說明了新建scrapy項(xiàng)目(zcool)spider項(xiàng)目(zc),這里不再贅述,然后得到我們的目錄結(jié)構(gòu)如下圖所示:

圖片

start.py文件

然后為了方便運(yùn)行,在zcool目錄下新建start文件。并進(jìn)行初始化設(shè)置。

from scrapy import cmdline
cmdline.execute('scrapy crawl zc'.split())

settings.py文件

在這個(gè)文件里我們需要做幾樣設(shè)置??

避免在程序運(yùn)行的時(shí)候打印log日志信息

  LOG_LEVEL = 'WARNING' 
 ROBOTSTXT_OBEY = False 

添加請求頭:

圖片

打開管道:圖片

item.py文件

import scrapy

class ZcoolItem(scrapy.Item):
    # define the fields for your item here like:
    imgLink = scrapy.Field() # 封面圖片鏈接
    title = scrapy.Field() # 標(biāo)題
    types = scrapy.Field() # 類型
    vistor = scrapy.Field() # 人氣
    comment = scrapy.Field() # 評論數(shù)
    likes = scrapy.Field() # 推薦人數(shù)

7.3 頁面數(shù)據(jù)提取

首先我們在站酷頁面使用xpath-helper測試一下:

圖片

然后zc.py文件里面初步測試一下:

def parse(self, response):
    divList = response.xpath('//div[@class='work-list-box']/div')
    print(len(divList))

運(yùn)行結(jié)果如下圖所示:圖片

沒有問題,然后我們對各種信息分別解析提取,

def parse(self, response):
    divList = response.xpath('//div[@class='work-list-box']/div')
    for div in divList:
        imgLink = div.xpath('./div[1]/a/img/@src').extract()[0# 1.封面圖片鏈接
  ...  2.title(標(biāo)題);3 types(類型);4vistor(人氣);5comment(評論數(shù))  ....
        likes = div.xpath('./div[2]/p[3]/span[3]/@title').extract_first() # 6likes(推薦人數(shù))

        item = ZcoolItem(imgLink=imgLink,title=title,types=types,vistor=vistor,comment=comment,likes=likes)

        yield item

解釋: xpath提取數(shù)據(jù)方法:

S.N.方法 & 描述
extract()返回的是符合要求的所有的數(shù)據(jù),存在一個(gè)列表里。
extract_first()返回的hrefs 列表里的第一個(gè)數(shù)據(jù)。
get()和extract_first()方法返回的是一樣的,都是列表里的第一個(gè)數(shù)據(jù)。
getall()和extract()方法一樣,返回的都是符合要求的所有的數(shù)據(jù),存在一個(gè)列表里。

注意:

get() 、getall() 方法是新的方法,extract() 、extract_first()方法是舊的方法。extract() 、extract_first()方法取不到就返回None。get() 、getall() 方法取不到就raise一個(gè)錯(cuò)誤。

item實(shí)例創(chuàng)建(yield上面一行代碼)

這里我們之前在目錄文件配置的item文件中已經(jīng)進(jìn)行了設(shè)置,對于數(shù)據(jù)存儲,我們在爬蟲文件中開頭要導(dǎo)入這個(gè)類:

from zcool.items import ZcoolItem

然后使用yield返回?cái)?shù)據(jù)。

為什么使用yield而不是return

不能使用return這個(gè)無容置疑,因?yàn)橐摚褂胷eturn直接退出函數(shù);而對于yield:在調(diào)用for的時(shí)候,函數(shù)內(nèi)部不會立即執(zhí)行,只是返回了一個(gè)生成器對象。在迭代的時(shí)候函數(shù)會開始執(zhí)行,當(dāng)在yield的時(shí)候,會返回當(dāng)前值(i)。之后的這個(gè)函數(shù)會在循環(huán)中進(jìn)行,直到?jīng)]有下一個(gè)值。

7.4 翻頁實(shí)現(xiàn)批量數(shù)據(jù)采集

通過上面的代碼已經(jīng)可以初步實(shí)現(xiàn)數(shù)據(jù)采集,只不過只有第一頁的,如下圖所示:

圖片

但是我們的目標(biāo)是100個(gè)頁面的批量數(shù)據(jù)采集,所以代碼還需要修改。針對翻頁這里介紹兩種方式:

方式一:我們首先在頁面中定位到下一頁的按鈕,如下圖所示:

圖片

然后編寫如下代碼,在for循環(huán)完畢后。

next_href = response.xpath('//a[@class='laypage_next']/@href').extract_first()
if next_href:
    next_url = response.urljoin(next_href)
    print('*' * 60)
    print(next_url)
    print('*' * 60)
    request = scrapy.Request(next_url)
    yield request

scrapy.Request(): 把下一頁的url傳遞給Request函數(shù),進(jìn)行翻頁循環(huán)數(shù)據(jù)采集。

https://www.cnblogs.com/heymonkey/p/11818495.html # scrapy.Request()參考鏈接

注意方式一只有下一頁按鈕它的href對應(yīng)屬性值和下一頁的url一致才行。

方式二:定義一個(gè)全局變量count = 0,每爬取一頁數(shù)據(jù),令其加一,構(gòu)建新的url,再使用scrapy.Request() 發(fā)起請求。

如下圖所示:

count = 1

class ZcSpider(scrapy.Spider):
    name = 'zc'
    allowed_domains = ['zcool.com.cn']
    start_urls = ['https://www.zcool.com.cn/home?p=1#tab_anchor'# 第一頁的url

    def parse(self, response):
        global count
        count  = 1
        
        for div in divList:
    # ...xxx...
            yield item

        next_url = 'https://www.kuaikanmanhua.com/tag/0?state=1&sort=1&page={}'.format(count)
        yield scrapy.Request(next_url)

這兩種方式在實(shí)際案例中擇機(jī)采用。

7.5 數(shù)據(jù)存儲

數(shù)據(jù)存儲是在pipline.py中進(jìn)行的,代碼如下:

from itemadapter import ItemAdapter
import csv

class ZcoolPipeline:
    def __init__(self): 
        self.f = open('Zcool.csv','w',encoding='utf-8',newline='')       # line1
        self.file_name = ['imgLink''title','types','vistor','comment','likes']  # line2
        self.writer = csv.DictWriter(self.f, fieldnames=self.file_name)     # line3
        self.writer.writeheader()              # line4

    def process_item(self, item, spider):
        self.writer.writerow(dict(item))              # line5
        print(item)
        return item                  # line6 

    def close_spider(self,spider):
        self.f.close()

解釋:

  • line1: 打開文件,指定方式為寫,利用第3個(gè)參數(shù)把csv寫數(shù)據(jù)時(shí)產(chǎn)生的空行消除

  • line2: 設(shè)置文件第一行的字段名,注意要跟spider傳過來的字典key名稱相同

  • line3: 指定文件的寫入方式為csv字典寫入,參數(shù)1為指定具體文件,參數(shù)2為指定字段名

  • line4: 寫入第一行字段名,因?yàn)橹灰獙懭胍淮?,所以文件放在__init__里面

  • line5: 寫入spider傳過來的具體數(shù)值,注意在spider文件中yield的item,是一個(gè)由類創(chuàng)建的實(shí)例對象,我們寫入數(shù)據(jù)時(shí),寫入的是 字典,所以這里還要轉(zhuǎn)化一下。

  • line6: 寫入完返回

7.6 程序運(yùn)行

因?yàn)橹皠?chuàng)建了start.py文件,并且對它就行了初始化設(shè)置,現(xiàn)在運(yùn)行爬蟲程序不需要在控制臺中輸入命令:

scrapy crawl zc(爬蟲項(xiàng)目名)

直運(yùn)行start.py文件:得到如下結(jié)果:

圖片

對應(yīng)于頁面:

圖片

打開csv文件如下圖所示:(由于csv文件在word中亂碼了,此處我是用Notepad 打開)

圖片

沒有問題,數(shù)據(jù)采集完畢。

7.7. 總結(jié)

入門案例,需要細(xì)心,主要是基礎(chǔ)知識的鞏固,以便于為進(jìn)階學(xué)習(xí)做好準(zhǔn)備。

作者:飲馬長江

來源:早起Python

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多