成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一日一技:Scrapy如何發起假請求?

開發 前端
最新版的Scrapy已經廢棄了start_requests?方法,改為start?方法了,這個方法天生就是async方法,可以直接在里面asyncio.sleep,也就不會再有上面的問題了。

在使用Scrapy的時候,我們可以通過在pipelines.py里面定義一些數據處理流程,讓爬蟲在爬到數據以后,先處理數據再儲存。這本來是一個很好的功能,但容易被一些垃圾程序員拿來亂用。

我看到過一些Scrapy爬蟲項目,它的代碼是這樣寫的:

...

def start_requests(self):
    yield scrapy.Request('https://baidu.com')

def parse(self, response):
    import pymongo
    handler = pymongo.MongoClient().xxdb.yycol
    rows = handler.find()
    for row in rows:
        yield row

這種垃圾代碼之所以會出現,是因為有一些垃圾程序員想偷懶,想復用Pipeline里面的代碼,但又不想單獨把它抽出來。于是他們沒有皺褶的腦子一轉,想到在Scrapy里面從數據庫讀取現成的數據,然后直接yield出來給Pipeline。但因為Scrapy必須在start_requests里面發起請求,不能直接yield數據,因此他們就想到先隨便請求一個url,例如百度,等Scrapy的callback進入了parse方法以后,再去讀取數據。

雖然請求百度,不用擔心反爬問題,響應大概率也是HTTP 200,肯定能進入parse,但這樣寫代碼怎么看怎么蠢。

有沒有什么辦法讓代碼看起來,即便蠢也蠢得高級一些呢?有,那就是發送假請求。讓Scrapy看起來發起了HTTP請求,但實際上直接跳過。

方法非常簡單,就是把URL寫成:data:,,注意末尾這個英文逗號不能省略。

于是你的代碼就會寫成:

def start_requests(self):
    yield scrapy.Request('data:,')

def parse(self, response):
    import pymongo
    handler = pymongo.MongoClient().xxdb.yycol
    rows = handler.find()
    for row in rows:
        yield row

這樣寫以后,即使你沒有外網訪問權限也沒問題,因為它不會真正發起請求,而是直接一晃而過,進入parse方法中。我把這種方法叫做發送假請求。

這個方法還有另外一個應用場景。看下面這個代碼:

def start_requests(self):
    while True:
        yield scrapy.Request('https://kingname.info/atom.xml', callback=self.parse, dont_filter=True)
        time.sleep(60)

def parse(self, response):
    ...對rss接口返回的數據進行處理...
    for item in xxx['items']:
        url = row['url']
        yield scrapy.Request(url, callback=self.parse_detail)

假如你需要讓爬蟲每分鐘監控一個URL,你可能會像上面這樣寫代碼。但由于Scrapy是基于Twisted實現的異步并發,因此time.sleep這種同步阻塞等待會把爬蟲卡住,導致在sleep的時候,parse里面發起的子請求全都會被卡住,于是爬蟲的并發數基本上等于1.

可能有同學知道Scrapy支持asyncio,于是想這樣寫代碼:

import asyncio


async def start_requests(self):
    while True:
        yield scrapy.Request('https://kingname.info/atom.xml', callback=self.parse, dont_filter=True)
        asyncio.sleep(60)

def parse(self, response):
    ...對rss接口返回的數據進行處理...
    for item in xxx['items']:
        url = row['url']
        yield scrapy.Request(url, callback=self.parse_detail)

但這樣寫會報錯,如下圖所示:

圖片圖片

這個問題的原因就在于start_requests這個入口方法不能使用async來定義。他需要至少經過一次請求,進入任何一個callback以后,才能使用async來定義。

這種情況下,也可以使用假請求來解決問題。我們可以把代碼改為:

求來解決問題。我們可以把代碼改為:

def start_requests(self):
    yield scrapy.Request('data:,', callback=self.make_really_req)

async def make_really_req(self, _):
    while True:
        yield scrapy.Request(url="https://kingname.com", callback=self.parse)
        await asyncio.sleep(60)

def parse(self, response):
    print(response.text)

這樣一來,使用了asyncio.sleep,既能實現60秒請求一次,又不會阻塞子請求了。

當然,最新版的Scrapy已經廢棄了start_requests方法,改為start方法了,這個方法天生就是async方法,可以直接在里面asyncio.sleep,也就不會再有上面的問題了。不過如果你使用的還是老版本的Scrapy,上面這個假請求的方法還是有點用處。

責任編輯:武曉燕 來源: 未聞Code
相關推薦

2021-10-03 20:08:29

HTTP2Scrapy

2021-06-08 21:36:24

PyCharm爬蟲Scrapy

2021-10-15 21:08:31

PandasExcel對象

2022-06-28 09:31:44

LinuxmacOS系統

2023-10-28 12:14:35

爬蟲JavaScriptObject

2022-03-12 20:38:14

網頁Python測試

2024-07-30 08:11:16

2024-07-30 08:16:18

Python代碼工具

2024-11-11 00:38:13

Mypy靜態類型

2021-05-08 19:33:51

移除字符零寬

2021-09-26 05:01:55

Scrapy項目爬蟲

2021-04-27 22:15:02

Selenium瀏覽器爬蟲

2020-12-11 06:30:00

工具分組DataFrame

2021-04-12 21:19:01

PythonMakefile項目

2022-03-07 09:14:04

Selenium鼠標元素

2024-02-20 22:13:48

Python項目Java

2020-05-19 13:55:38

Python加密密碼

2024-08-27 22:08:13

2021-02-14 22:22:18

格式圖片 HTTP

2021-09-13 20:38:47

Python鏈式調用
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 狠狠入ady亚洲精品经典电影 | 中文字幕精品一区久久久久 | 精品福利在线 | 欧美福利影院 | 欧美精品一区二区在线观看 | 9久久精品| 在线国产视频 | 网址黄 | 激情在线视频网站 | 欧美aⅴ在线观看 | 欧美性视频在线播放 | 99re | 日日夜夜天天 | 国产资源在线视频 | 久久成人免费观看 | av中文字幕在线观看 | 精品一区二区久久久久久久网站 | 国产视频中文字幕 | 午夜影晥 | 无码一区二区三区视频 | av黄色片在线观看 | 久久免费精品 | 99久久免费精品 | 午夜精品久久久久久不卡欧美一级 | 日韩精品久久一区二区三区 | 99久久精品免费看国产四区 | 国产在线永久免费 | 国产日韩电影 | 亚洲国产视频一区二区 | 亚洲精品久久久一区二区三区 | 成av在线| 黄色大片免费网站 | 久久精品99国产精品日本 | 亚洲综合一区二区三区 | 成人在线播放 | 国产精品自拍视频网站 | 亚洲国产一区二区三区 | 综合婷婷| 欧美日韩国产一区二区三区 | 伊人久久大香线 | 欧美一级免费 |