前言
一個月沒更博客了,這個月也搞了不少東西,但是公司對保密性要求挺高,很多東西都沒有辦法寫出來
想來想去,還是寫一篇最近寫Scrapy中遇到的跳轉問題
如果你的業務需求是遇到301/302/303跳轉的請求時繼續請求網址,直到獲取到最終的真實數據為止,那么這篇文章將會非常適合你
正文
隊列選型
我們在使用SCRAPY中通常會使用分布式來提高爬取效率,所以需要一個任務隊列來進行任務的下發,通常,該隊列還承擔着爬取的結果進行收集交由某幾個Worker進行入庫的作用
如果使用Redis作為任務隊列,推薦使用 scrapy-redis 教程很多,這里不多說
這里着重介紹使用 RabbitMQ 作為任務隊列,RabbitMQ的好處有很多,但是還是建議跟着業務走.
使用RabbitMQ作為任務隊列
使用RabbitMQ作為任務隊列的輪子很少,基本都已停止更新(17年),這里推薦一個國人的修改版,最近才開始發布,但是經本人實測已經可以正常使用
項目地址(GitHub)scrapy-rabbitmq-scheduler
因是國人寫的,所以README文件寫的通俗易懂.
安裝
pip install scrapy-rabbitmq-scheduler
集成至Scrapy
在settings.py最后加入
# 指定項目的調度器
SCHEDULER = "scrapy_rabbitmq_scheduler.scheduler.SaaS"
# 指定rabbitmq的連接DSN
# amqp_url="amqp://username:password@ip:port/"
RABBITMQ_CONNECTION_PARAMETERS = 'amqp://admin:pwd@x.x.x.x:5672/'
# 指定重試的http狀態碼(重新加回隊列重試)
# 如果結果的狀態碼位該list其中一個則會重試
# SCHEDULER_REQUEUE_ON_STATUS = [500]
# 指定下載器中間件, 確認任務是否成功
DOWNLOADER_MIDDLEWARES = {
'scrapy_rabbitmq_scheduler.middleware.RabbitMQMiddleware': 999
}
# 指定item處理方式, item會加入到rabbitmq中
ITEM_PIPELINES = {
'scrapy_rabbitmq_scheduler.pipelines.RabbitmqPipeline': 300,
}
爬蟲編寫
這里與Scrapy原來的方式稍有不同
構造發送請求/接收RabbitMQ數據的方法名為 _make_request
我們必須重構該方法才可正常運行使用爬蟲
該方法起到每次從隊列中拿取數據后的解析數據並進行請求的作用
通常我們存放在隊列中的一個數據為一個JSON/msgpack格式,里面包含了要請求的URl/該條數據所屬ID等多個信息
必須要注意的是如果遇到跳轉或你在setting中設置了返回狀態碼為xxx重新爬取,那么Scrapy會將需要重新爬取的url存放至你的隊列中,此時隊列中有兩種格式的數據
- 上游生產者發送的符合你的通信協議的數據(JSON/msgpack)
- Scrapy自己加入的需要重新爬取的數據
所以我們要對這兩種數據加以區分
爬蟲示例
item是對返回數據序列化的,item
運行爬蟲后,scrapy獲取到的數據會轉JSON傳送至res_status_ok
中(你自定義的)
添加個Work在隊列另一端接收入庫或其他操作即可
需要注意的點
Scrapy自己插入數據到分發隊列
當時被這個問題卡了一小時,網上是沒有解決方法的,他生成的數據也是不能使用常規方法進行解碼的,這常常令人一頭霧水
通道設置
該組件默認RabbitMQ持久化為True,因此請注意建立通道的時候將設置對齊否則會出現因為設置錯誤導致無法連接的問題