亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

一、Scrapy框架簡(jiǎn)介

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

Scrapy使用了Twisted異步網(wǎng)絡(luò)框架來處理網(wǎng)絡(luò)通信,可以加快我們的下載速度,不用自己去實(shí)現(xiàn)異步框架,并且包含了各種中間件接口,可以靈活地實(shí)現(xiàn)各種需求。

Scrapy可以應(yīng)用在包括數(shù)據(jù)挖掘、信息處理或存儲(chǔ)歷史數(shù)據(jù)等一系列的程序中,其最初是為頁面抓取(更確切地說是網(wǎng)絡(luò)抓取)而設(shè)計(jì)的,也可以應(yīng)用于獲取API所返回的數(shù)據(jù)(例如Amazon Associates Web Services)或者通用的網(wǎng)絡(luò)爬蟲。

二、Scrapy架構(gòu)

1、架構(gòu)圖

官方架構(gòu)圖

 

翻譯架構(gòu)圖

 

2、組件

Scrapy主要包括了以下組件:

  • 爬蟲中間件(Spider Middleware):位于Scrapy引擎和爬蟲之間的框架,主要用于處理爬蟲的響應(yīng)輸入和請(qǐng)求輸出。
  • 調(diào)度器中間件(Scheduler Middleware):位于Scrapy引擎和調(diào)度器之間的框架,主要用于處理從Scrapy引擎發(fā)送到調(diào)度器的請(qǐng)求和響應(yīng)。
  • 調(diào)度器(Scheduler):用來接收引擎發(fā)過來的請(qǐng)求,壓入隊(duì)列中,并在引擎再次請(qǐng)求的時(shí)候返回。它就像是一個(gè)URL的優(yōu)先隊(duì)列,由它來決定下一個(gè)要抓取的網(wǎng)址是什么,同時(shí)在這里會(huì)去除重復(fù)的網(wǎng)址。
  • 下載器中間件(Downloader Middleware):位于Scrapy引擎和下載器之間的框架,主要用于處理Scrapy引擎與下載器之間的請(qǐng)求及響應(yīng)。代理IP和用戶代理可以在這里設(shè)置。
  • 下載器(Downloader):用于下載網(wǎng)頁內(nèi)容,并將網(wǎng)頁內(nèi)容返回給爬蟲。

Scrapy引擎(ScrapyEngine):用來控制整個(gè)系統(tǒng)的數(shù)據(jù)處理流程,并進(jìn)行事務(wù)處理的觸發(fā)。

  • 爬蟲(Spiders):爬蟲主要是干活的,用于從特定網(wǎng)頁中提取自己需要的信息,即所謂的項(xiàng)目(又稱實(shí)體)。也可以從中提取URL,讓Scrapy繼續(xù)爬取下一個(gè)頁面。
  • 項(xiàng)目管道(Pipeline):負(fù)責(zé)處理爬蟲從網(wǎng)頁中爬取的項(xiàng)目,主要的功能就是持久化項(xiàng)目、驗(yàn)證項(xiàng)目的有效性、清除不需要的信息。當(dāng)頁面被爬蟲解析后,將被送到項(xiàng)目管道,并經(jīng)過幾個(gè)特定的次序來處理其數(shù)據(jù)。

3、運(yùn)行流程

數(shù)據(jù)流(Data flow),Scrapy中的數(shù)據(jù)流由執(zhí)行引擎(ScrapyEngine)控制,其過程如下:

  1. 引擎打開一個(gè)網(wǎng)站(open a domain),找到處理該網(wǎng)站的Spider并向該spider請(qǐng)求第一個(gè)要爬取的URL(s)。
  2. 引擎從Spider中獲取到第一個(gè)要爬取的URL并在調(diào)度器(Scheduler)以Request調(diào)度。
  3. 引擎向調(diào)度器請(qǐng)求下一個(gè)要爬取的URL。
  4. 調(diào)度器返回下一個(gè)要爬取的URL給引擎,引擎將URL通過下載中間件(請(qǐng)求(request)方向)轉(zhuǎn)發(fā)給下載器(Downloader)。
  5. 一旦頁面下載完畢,下載器生成一個(gè)該頁面的Response,并將其通過下載中間件(返回(response)方向)發(fā)送給引擎。
  6. 引擎從下載器中接收到Response并通過Spider中間件(輸入方向)發(fā)送給Spider處理。
  7. Spider處理Response并返回爬取到的Item及(跟進(jìn)的)新的Request給引擎。
  8. 引擎將(Spider返回的)爬取到的Item給Item Pipeline,將(Spider返回的)Request給調(diào)度器。
  9. (從第二步)重復(fù)直到調(diào)度器中沒有更多地request,引擎關(guān)閉該網(wǎng)站

三、Scrapy安裝以及生成項(xiàng)目

1、下載安裝

linux下載方式,直接安裝

pip install scrapy
或者
pip3 install scrapy)

windows 如果用Pycharm的話,在Pycharm底部打開命令終端

 

輸入命令

pip install scrapy

 

2、創(chuàng)建Scrapy項(xiàng)目

#創(chuàng)建一個(gè)叫ScrapyDemmo
scrapy startproject ScrapyDemmo
#進(jìn)入項(xiàng)目文件夾
cd ScrapyDemmo
#創(chuàng)建一個(gè)名為baidu的爬蟲,爬蟲目標(biāo)www.baidu.com
scrapy genspider baidu www.baidu.com

創(chuàng)建完成后,目錄結(jié)構(gòu)如下:

 

  • scrapy.cfg: 項(xiàng)目的配置文件。
  • scrapyspider/: 該項(xiàng)目的python模塊。之后您將在此加入代碼。
  • scrapyspider/items.py: 項(xiàng)目中的item文件。
  • scrapyspider/pipelines.py: 項(xiàng)目中的pipelines文件。
  • scrapyspider/settings.py: 項(xiàng)目的設(shè)置文件。
  • scrapyspider/spiders/: 放置spider代碼的目錄。

spiders下的baidu.py是scrapy用命令(scrapy genspider baidu www.baidu.com)自動(dòng)為我們生成的。

內(nèi)容如下:

import scrapy

class BaiduSpider(scrapy.Spider):
    name = 'baidu'
    allowed_domains = ['www.baidu.com']
    start_urls = ['http://www.baidu.com/']

    def parse(self, response):
        title = response.xpath('//html/dead/title/text()')
        print(title)

當(dāng)然,可以不用命令生成,可以自己在spiders下創(chuàng)建爬蟲,您必須繼承 scrapy.Spider 類, 且定義以下三個(gè)屬性:

  • name: 用于區(qū)別Spider。 該名字必須是唯一的,您不可以為不同的Spider設(shè)定相同的名字。
  • start_urls: 包含了Spider在啟動(dòng)時(shí)進(jìn)行爬取的url列表。 因此,第一個(gè)被獲取到的頁面將是其中之一。 后續(xù)的URL則從初始的URL獲取到的數(shù)據(jù)中提取。
  • parse() 是spider的一個(gè)方法。 被調(diào)用時(shí),每個(gè)初始URL完成下載后生成的 Response 對(duì)象將會(huì)作為唯一的參數(shù)傳遞給該函數(shù)。 該方法負(fù)責(zé)解析返回的數(shù)據(jù)(response data),提取數(shù)據(jù)(生成item)以及生成需要進(jìn)一步處理的URL的 Request 對(duì)象。

3、運(yùn)行爬蟲

運(yùn)行方法:

在項(xiàng)目目錄底下用命令運(yùn)行,如下,我項(xiàng)目目錄 D:PythonScrapyDemmo,運(yùn)行name為baidu的爬蟲

D:PythonScrapyDemmo> scrapy crawl baidu

 

在scrapy中,為了避免每一次運(yùn)行或調(diào)試都輸入一串命令,可以在項(xiàng)目文件下新建一個(gè)run.py文件,每次運(yùn)行爬蟲只需要運(yùn)行此腳本即可。且運(yùn)行調(diào)試模式也需要設(shè)置此啟動(dòng)腳本。

from scrapy import cmdline

cmdline.execute("scrapy crawl baidu".split())

最后運(yùn)行這個(gè)run.py即可,執(zhí)行結(jié)果:

D:PythonvenvScriptspython.exe D:PythonScrapyDemmoScrapyDemmorun.py 
2022-10-28 10:12:55 [scrapy.utils.log] INFO: Scrapy 2.7.0 started (bot: ScrapyDemmo)
2022-10-28 10:12:55 [scrapy.utils.log] INFO: Versions: lxml 4.9.1.0, libxml2 2.9.12, cssselect 1.1.0, parsel 1.6.0, w3lib 2.0.1, Twisted 22.8.0, Python 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)], pyOpenSSL 22.1.0 (OpenSSL 3.0.5 5 Jul 2022), cryptography 38.0.1, Platform Windows-10-10.0.22000-SP0
2022-10-28 10:12:55 [scrapy.crawler] INFO: Overridden settings:
{'BOT_NAME': 'ScrapyDemmo',
 'NEWSPIDER_MODULE': 'ScrapyDemmo.spiders',
 'REQUEST_FINGERPRINTER_IMPLEMENTATION': '2.7',
 'ROBOTSTXT_OBEY': True,
 'SPIDER_MODULES': ['ScrapyDemmo.spiders'],
 'TWISTED_REACTOR': 'twisted.inte.NET.asyncioreactor.AsyncIOSelectorReactor'}
2022-10-28 10:12:55 [asyncio] DEBUG: Using selector: SelectSelector
...
...

若嫌棄scrapy日志文件太雜亂,想無日志輸出,只需在后面增加--nolog即可:

from scrapy import cmdline

cmdline.execute('scrapy crawl baidu --nolog'.split())

執(zhí)行導(dǎo)出為json或scv格式,執(zhí)行爬蟲文件時(shí)添加-o選項(xiàng)即可

scrapy crawl 項(xiàng)目名 -o *.csv

scrapy crawl 項(xiàng)目名 -o *.json

對(duì)于json文件,在setting.js文件里添加,設(shè)置編碼格式,否則會(huì)亂碼:

from scrapy import cmdline
 
cmdline.execute('scrapy crawl baidu -o baidu.csv'.split())

四、Scrapy配置文件settings.py

默認(rèn)配置文件,主要設(shè)置參數(shù):

BOT_NAME = 'ScrapyDemmo' #Scrapy項(xiàng)目的名字,這將用來構(gòu)造默認(rèn) User-Agent,同時(shí)也用來log,當(dāng)您使用 startproject 命令創(chuàng)建項(xiàng)目時(shí)其也被自動(dòng)賦值。

SPIDER_MODULES = ['ScrapyDemmo.spiders'] #Scrapy搜索spider的模塊列表 默認(rèn): [xxx.spiders]
NEWSPIDER_MODULE = 'ScrapyDemmo.spiders' #使用 genspider 命令創(chuàng)建新spider的模塊。默認(rèn): 'xxx.spiders'  


#爬取的默認(rèn)User-Agent,除非被覆蓋 
#USER_AGENT = 'ScrapyDemmo (+http://www.yourdomain.com)'

#如果啟用,Scrapy將會(huì)采用 robots.txt策略 
ROBOTSTXT_OBEY = True

#Scrapy downloader 并發(fā)請(qǐng)求(concurrent requests)的最大值,默認(rèn): 16 
#CONCURRENT_REQUESTS = 32

#為同一網(wǎng)站的請(qǐng)求配置延遲(默認(rèn)值:0) 
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
#DOWNLOAD_DELAY = 3 #下載器在下載同一個(gè)網(wǎng)站下一個(gè)頁面前需要等待的時(shí)間,該選項(xiàng)可以用來限制爬取速度,減輕服務(wù)器壓力。同時(shí)也支持小數(shù):0.25 以秒為單位  

#下載延遲設(shè)置只有一個(gè)有效 
#CONCURRENT_REQUESTS_PER_DOMAIN = 16  #對(duì)單個(gè)網(wǎng)站進(jìn)行并發(fā)請(qǐng)求的最大值。
#CONCURRENT_REQUESTS_PER_IP = 16	#對(duì)單個(gè)IP進(jìn)行并發(fā)請(qǐng)求的最大值。如果非0,則忽略

#禁用Cookie(默認(rèn)情況下啟用) 
#COOKIES_ENABLED = False

#禁用Telnet控制臺(tái)(默認(rèn)啟用) 
#TELNETCONSOLE_ENABLED = False

#覆蓋默認(rèn)請(qǐng)求標(biāo)頭:  
#DEFAULT_REQUEST_HEADERS = {
#   'Accept': 'text/html,Application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
#   'Accept-Language': 'en',
#}

#項(xiàng)目管道,300為優(yōu)先級(jí),越低越爬取的優(yōu)先度越高
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
#ITEM_PIPELINES = {
#    'ScrapyDemmo.pipelines.ScrapydemmoPipeline': 300,
#}

還可以設(shè)置日志的等級(jí)與日志存放的路徑:

相關(guān)變量

LOG_LEVEL= ""
LOG_FILE="日志名.log"

日志等級(jí)分為,默認(rèn)等級(jí)是1

  1. DEBUG 調(diào)試信息
  2. INFO 一般信息
  3. WARNING 警告
  4. ERROR 普通錯(cuò)誤
  5. CRITICAL 嚴(yán)重錯(cuò)誤

如果設(shè)置

LOG_LEVEL="WARNING",就只會(huì)WARNING等級(jí)之下的ERROR和CRITICAL

一般主要需要配置的幾個(gè)參數(shù),其他按需配置即可。

USER_AGENT:默認(rèn)是注釋的,這個(gè)東西非常重要,如果不寫很容易被判斷為電腦爬蟲。

ROBOTSTXT_OBEY:是否遵循機(jī)器人協(xié)議,默認(rèn)是true,需要改為false,否則很多東西爬不了

DEFAULT_REQUEST_HEADERS:和USER_AGENT類似,只是參數(shù)更完整。

五、完整案例(下載圖片)

用scrapy框架下載以前的示例:python爬蟲之批量下載圖片

1、修改settings.py 主要參數(shù)

#關(guān)閉robot.txt協(xié)議
ROBOTSTXT_OBEY = False

#頁面延遲下載,我這里測(cè)試,可以先不設(shè)置
DOWNLOAD_DELAY = 1

# 是否啟用Cookie
COOKIES_ENABLED = True

#請(qǐng)求頭 
DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
  'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36'
}
#打開下載器
DOWNLOADER_MIDDLEWARES = {
    'ScrapyDemmo.middlewares.ScrapydemmoDownloaderMiddleware': 543,
}
#打開優(yōu)先級(jí),并添加自己編寫的圖片下載管道
ITEM_PIPELINES = {
   'ScrapyDemmo.pipelines.ScrapydemmoPipeline': 300,
   'ScrapyDemmo.pipelines.ImageDownloadPipeline': 300,
}
#添加下載儲(chǔ)存目錄
IMAGES_STORE = 'D:Pythonpic'

# 文件保存時(shí)間
#IMAGES_EXPIRES = 90

2、定義Item字段(Items.py)

本項(xiàng)目用于下載圖片,因此可以僅構(gòu)建圖片名和圖片地址字段。

import scrapy


class ScrapydemmoItem(scrapy.Item):
	#圖片下載鏈接
    image_url = scrapy.Field()
    #圖片名稱
    image_name = scrapy.Field()

3、編寫爬蟲文件(spiders目錄下)

這里文件名為:image_download.py

以前用requests庫和BeautifulSoup庫下載圖片,這里就不需要了,scrapy自帶相關(guān)函數(shù)和方法。

scrapy元素定位,提供三種方式,正則、Xpath表達(dá)式、css。

我這里有xpath定位方式。

import scrapy
import re
from ..items import ScrapydemmoItem

class ImageSpider(scrapy.Spider):
    name = 'image_download'
    allowed_domains = ['desk.3gbizhi.com']
    start_urls = ['https://desk.3gbizhi.com/deskMV/index.html']

    def parse(self, response):
    	#導(dǎo)入Items.py字段
        items = ScrapydemmoItem()
        #獲取所有鏈接列表
        lists = response.xpath('//div[5]/ul/li')
        #點(diǎn)位元素循環(huán)獲取圖片鏈接和圖片名稱
        for i in lists:
        	#圖片名稱
            image_name = i.xpath('./a/img/@alt').get()
            #圖片鏈接
            items['image_url'] = i.xpath('./a/img/@*[1]').get().replace('.278.154.jpg', '')
            #圖片格式類型
            image_type = re.sub(r'h.*d+.', '', items['image_url'])
            #拼接文件名,圖片名稱+圖片格式
            items['image_name'] = '{}.{}'.format(image_name, image_type)
            yield  items
		#循環(huán)跳轉(zhuǎn)下一頁,并重復(fù)返回?cái)?shù)據(jù),這里測(cè)試先下載1頁的圖片,總共23頁。
        for i in range(2,3):
            next_url = 'https://desk.3gbizhi.com/deskMV/index_{}.html'.format(i)
            yield scrapy.Request(next_url,callback=self.parse)

關(guān)于 yield 的理解,?先,如果你還沒有對(duì)yield有個(gè)初步分認(rèn)識(shí),那么你先把yield看做“return”,這個(gè)是直觀的,它?先是個(gè)return。

最主要的不同在于yield在返回值后還可以繼續(xù)運(yùn)行接下來的代碼,使用的函數(shù)會(huì)返回一個(gè)生成器,而return在返回后就不在執(zhí)行代碼。

以上兩個(gè)yield:

  • yield items:這里我們通過 yield 返回的不是 Request 對(duì)象,而是一個(gè) ScrapydemmoItem 對(duì)象。scrap有框架獲得這個(gè)對(duì)象之后,會(huì)將這個(gè)對(duì)象傳遞給 pipelines.py來做進(jìn)一步處理。我們將在 pipelines.py里將傳遞過來的 scrapy.Item 對(duì)象保存到數(shù)據(jù)庫里去。
  • yield scrapy.Request:這里是在爬取完一頁的信息后,我們?cè)诋?dāng)前頁面獲取到了下一頁的鏈接,然后通過 yield 發(fā)起請(qǐng)求,并且將 parse 自己作為回調(diào)函數(shù)來處理下一頁的響應(yīng)。

4、修改管道文件pipelines.py用于下載圖片

除了爬取文本,我們可能還需要下載文件、視頻、圖片、壓縮包等,這也是一些常見的需求。scrapy提供了FilesPipeline和ImagesPipeline,專門用于下載普通文件及圖片。

繼承 Scrapy 內(nèi)置的 ImagesPipeline,只需要重寫get_media_requests 和item_completed函數(shù)即可。

from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
from scrapy import Request

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

class ImageDownloadPipeline(ImagesPipeline):
    def get_media_requests(self, item, info):
    	# 下載圖片,如果傳過來的是集合需要循環(huán)下載
    	# meta里面的數(shù)據(jù)是從spider獲取,然后通過meta傳遞給下面方法:file_path
        yield Request(url = item['image_url'],meta = {'filename':item['image_name']})

    def item_completed(self, results, item, info):
     	# 分析下載結(jié)果并剔除下載失敗的圖片
        image_paths = [x['path'] for ok, x in results if ok]
        if not image_paths:
            raise DropItem("Item contains no images")
        return item

    def file_path(self, request, response=None, info=None):
    	# 接收上面meta傳遞過來的圖片名稱
        file_name = request.meta['filename']
        return file_name
  • get_media_requests()。它的第一個(gè)參數(shù) item 是爬取生成的 Item 對(duì)象。我們將它的 url 字段取出來,然后直接生成 Request 對(duì)象。此 Request 加入調(diào)度隊(duì)列,等待被調(diào)度,執(zhí)行下載。
  • item_completed(),它是當(dāng)單個(gè) Item 完成下載時(shí)的處理方法。因?yàn)榭赡苡袀€(gè)別圖片未成功下載,所以需要分析下載結(jié)果并剔除下載失敗的圖片。該方法的第一個(gè)參數(shù) results 就是該 Item 對(duì)應(yīng)的下載結(jié)果,它是一個(gè)列表形式,列表每一個(gè)元素是一個(gè)元組,其中包含了下載成功或失敗的信息。這里我們遍歷下載結(jié)果找出所有成功的下載列表。如果列表為空,那么說明該 Item 對(duì)應(yīng)的圖片下載失敗了,隨即拋出異常DropItem,該 Item 忽略。否則返回該 Item,說明此 Item 有效。

以上兩個(gè)函數(shù)即可下載圖片了,圖片名稱為自動(dòng)已哈希值命名,如:
0db6e07054d966513f0a6f315b687f205c7ced90.jpg 這種命名方式不友好,所以我們需要重寫 file_path函數(shù),自定義圖片名稱。

  • file_path():它的第一個(gè)參數(shù) request 就是當(dāng)前下載對(duì)應(yīng)的 Request 對(duì)象。這個(gè)方法用來返回保存的文件名,接收上面meta傳遞過來的圖片名稱,將圖片以原來的名稱和定義格式進(jìn)行保存。

5、編寫執(zhí)行文件run.py運(yùn)行

在項(xiàng)目下新建run.py作為執(zhí)行文件

from scrapy import cmdline

#cmdline.execute('scrapy crawl image_download --nolog'.split())
cmdline.execute('scrapy crawl image_download'.split())

運(yùn)行此文件,執(zhí)行結(jié)果,在目錄下載第一頁壁紙完成。

 

六、小結(jié)

除了 ImagesPipeline 處理圖片外,還有 FilesPipeline 可以處理文件,使用方法與圖片類似,事實(shí)上 ImagesPipeline 是 FilesPipeline 的子類,因?yàn)閳D片也是文件的一種。

Scrapy很強(qiáng)大,對(duì)于大型網(wǎng)站非常實(shí)用,還可以同時(shí)運(yùn)行多個(gè)爬蟲程序,提升效率。Scrapy還有很多功能,可以自己研究。

分享到:
標(biāo)簽:Scrapy
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定