基于 scrapy-redis 的通用分布式爬蟲框架

spiderman

基于 scrapy-redis 的通用分布式爬蟲框架

開源地址 https://github.com/TurboWay/spiderman


目錄

demo采集效果

image
image
image

爬蟲元數(shù)據(jù)

meta

cluster模式

cluster

standalone模式

standalone

附件下載

image-20210318161618307

kafka實(shí)時采集監(jiān)控

mon

功能

  • 自動建表

  • 自動生成爬蟲代碼收壕,只需編寫少量代碼即可完成分布式爬蟲

  • 自動存儲元數(shù)據(jù)蒋得,分析統(tǒng)計和補(bǔ)爬都很方便

  • 適合多站點(diǎn)開發(fā)窝稿,每個爬蟲獨(dú)立定制籽腕,互不影響

  • 調(diào)用方便础废,可以根據(jù)傳參自定義采集的頁數(shù)以及啟用的爬蟲數(shù)量

  • 擴(kuò)展簡易姑尺,可以根據(jù)需要選擇采集模式厂抖,單機(jī) standalone (默認(rèn)) 或者 分布式cluster

  • 采集數(shù)據(jù)落地方便灸眼,支持多種數(shù)據(jù)庫卧檐,只需在 spider 中啟用相關(guān)的管道

    關(guān)系型

    • mysql
    • sqlserver
    • oracle
    • postgresql
    • sqlite3

    非關(guān)系型

    • hbase
    • mongodb
    • elasticsearch
    • hdfs
    • hive
    • datafile, 比如 csv
  • 反爬處理簡易,已封裝各種反爬中間件

    • 隨機(jī) UserAgent
    • 定制請求頭 Headers
    • 定制 Cookies 池
    • 定制代理 ip
    • 在 scrapy 中使用 requests
    • Payload 請求
    • 使用 Splash 渲染 js

原理說明

  1. 消息隊列使用 redis幢炸,采集策略使用廣度優(yōu)先泄隔,先進(jìn)先出
  2. 每個爬蟲都有一個 job 文件,使用 job 來生成初始請求類 ScheduledRequest宛徊,并將其推送到 redis佛嬉;
    初始請求全部推到 redis 后,運(yùn)行 spider 解析生成數(shù)據(jù) 并迭代新的請求到redis, 直到 redis 中的全部請求被消耗完
# scrapy_redis請求類
class ScheduledRequest:

    def __init__(self, **kwargs):
        self.url = kwargs.get('url')                 # 請求url
        self.method = kwargs.get('method', 'GET')   # 請求方式 默認(rèn)get
        self.callback = kwargs.get('callback')  # 回調(diào)函數(shù)闸天,指定spider的解析函數(shù)
        self.body = kwargs.get('body')  # body, method為post時, 作為 post表單
        self.meta = kwargs.get('meta')  # meta, 攜帶元數(shù)據(jù)暖呕,比如 pagenum
  1. item 類定義表名、字段名苞氮、排序號(自定義字段順序)湾揽、注釋說明(便于管理元數(shù)據(jù))、字段類型(僅關(guān)系型數(shù)據(jù)庫管道有效)
class zhifang_list_Item(scrapy.Item):
    #  define table
    tablename = 'zhifang_list'
    tabledesc = '列表'
    # define the fields for your item here like:
    # 關(guān)系型數(shù)據(jù)庫,可以自定義字段的類型库物、長度霸旗,默認(rèn) VARCHAR(length=255)
    # colname = scrapy.Field({'idx': 1, 'comment': '名稱', 'type': VARCHAR(255)})
    tit = scrapy.Field({'idx': 1, 'comment': '房屋標(biāo)題'})
    txt = scrapy.Field({'idx': 2, 'comment': '房屋描述'})
    tit2 = scrapy.Field({'idx': 3, 'comment': '房屋樓層'})
    price = scrapy.Field({'idx': 4, 'comment': '房屋價格'})
    agent = scrapy.Field({'idx': 5, 'comment': '房屋中介'})
    # default column
    detail_full_url = scrapy.Field({'idx': 100, 'comment': '詳情鏈接'})  # 通用字段
    pkey = scrapy.Field({'idx': 101, 'comment': 'md5(detail_full_url)'})  # 通用字段
    pagenum = scrapy.Field({'idx': 102, 'comment': '頁碼'})  # 通用字段
  1. 去重策略,默認(rèn)不去重戚揭,每次采集獨(dú)立诱告,即每次啟動 job 都會清空上一次未完成的 url,并且不保留 redis 中上一次已采集的 url 指紋民晒。
    如需調(diào)整可以修改以下配置
  • job 文件(單個爬蟲)
class zhifang_job(SPJob):

    def __init__(self):
        super().__init__(spider_name=zhifang_Spider.name)
        # self.delete()   # 如需去重精居、增量采集,請注釋該行
  • spider 文件(單個爬蟲)
    custom_settings = {
        ...,
        'DUPEFILTER_CLASS': 'scrapy_redis.dupefilter.RFPDupeFilter',
        'SCHEDULER_PERSIST': True, # 開啟持久化
    }
   
    def get_callback(self, callback):
        # url去重設(shè)置:True 不去重 False 去重
        callback_dt = {
            'list': (self.list_parse, False),
            'detail': (self.detail_parse, False),
        }
        return callback_dt.get(callback)
  • 布隆過濾器潜必。

當(dāng)采集的數(shù)據(jù)量很大時靴姿,可以使用布隆過濾器,該算法占用空間小且可控磁滚,適合海量數(shù)據(jù)去重佛吓。
但是該算法會有漏失率,對爬蟲而言就是漏爬恨旱”蔡海可以通過調(diào)整過濾器負(fù)載個數(shù)、內(nèi)存配置搜贤、哈希次數(shù)以降低漏失率谆沃。
默認(rèn) 1 個過濾器,256 M 內(nèi)存仪芒,使用 7 個 seeds唁影,這個配置表示漏失概率為 8.56e-05 時,可滿足 0.93 億條字符串的去重掂名。當(dāng)漏失率為 0.000112 時据沈,可滿足 0.98 億條字符串的去重。調(diào)參與漏失率參考

    custom_settings = {
        ...,
        'DUPEFILTER_CLASS': 'SP.bloom_dupefilter.BloomRFDupeFilter',  # 使用布隆過濾器
        'SCHEDULER_PERSIST': True,  # 開啟持久化
        'BLOOM_NUM': 1,  # 布隆過濾器負(fù)載個數(shù)饺蔑,當(dāng)內(nèi)存達(dá)到限制時锌介,可以增加負(fù)載個數(shù)
        'BLOOM_MEM': 256,  # 布隆過濾器內(nèi)存大小(單位 M)猾警,內(nèi)存最大 512 M (因為 redis string 最大只能 512 M)
        'BLOOM_K': 7,  # 布隆過濾器哈希次數(shù)孔祸,次數(shù)越少,去重越快发皿,但是漏失率越高
    }
   
    def get_callback(self, callback):
        # url去重設(shè)置:True 不去重 False 去重
        callback_dt = {
            'list': (self.list_parse, False),
            'detail': (self.detail_parse, False),
        }
        return callback_dt.get(callback)

下載安裝

  1. git clone https://github.com/TurboWay/spiderman.git; cd spiderman;
  2. 【不使用虛擬環(huán)境的話崔慧,可以跳過步驟23】virtualenv -p /usr/bin/python3 venv
  3. 【不使用虛擬環(huán)境的話,可以跳過步驟23】source venv/bin/activate
  4. pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
  5. 修改配置 vi SP/settings.py
  6. 運(yùn)行demo示例 python SP_JOBS/zhifang_job.py

如何開發(fā)一個新爬蟲

運(yùn)行 easy_scrapy.py 會根據(jù)模板自動生成以下代碼文件穴墅,并自動在編輯器打開 spidername_job.py 文件惶室;

類別 路徑 說明
job SP_JOBS/spidername_job.py 編寫初始請求
spider SP/spiders/spidername.py 編寫解析規(guī)則温自,產(chǎn)生新的請求
items SP/items/spidername_items.py 定義表名字段

以上代碼文件編寫完成后,直接執(zhí)行 python SP_JOBS/spidername_job.py

或者動態(tài)傳參(參數(shù)說明 -p 采集頁數(shù)皇钞, -n 啟用爬蟲數(shù)量) python SP_JOBS/spidername_job.py -p 10 -n 1

如何進(jìn)行補(bǔ)爬

運(yùn)行 easy_scrapy.py 會根據(jù)模板自動生成以下代碼文件悼泌,并自動在編輯器打開 spidername_job_patch.py 文件;

類別 路徑 說明
job SP_JOBS/spidername_job_patch.py 編寫補(bǔ)爬請求

以上代碼文件編寫完成后鹅士,直接執(zhí)行 python SP_JOBS/spidername_job_patch.py

如何下載附件

提供兩種方式下載:

  • 1券躁、直接在 spider 中啟用附件下載管道
  • 2、使用自定義的下載器 execute_download.py 傳參下載

jpg/pdf/word...等各種各樣的文件掉盅,統(tǒng)稱為附件。
下載附件是比較占用帶寬的行為以舒,所以在大規(guī)模采集中趾痘,最好是先把結(jié)構(gòu)化的表數(shù)據(jù)、附件的元數(shù)據(jù)入庫蔓钟,
保證數(shù)據(jù)的完整性永票,然后再根據(jù)需要,通過下載器進(jìn)行附件下載滥沫。

如何擴(kuò)展分布式爬蟲

采集模式有兩種(在 settings 控制): 單機(jī) standalone(默認(rèn)) 和 集群分布式

如果想切換成分布式爬蟲侣集,需要在 spiderman/SP/settings.py 中啟用以下配置

<font color='red'> 注意:前提是 所有SLAVE機(jī)器的爬蟲代碼一致、python環(huán)境一致兰绣,都可以運(yùn)行爬蟲demo </font>

# 集群模式 False 單機(jī) (默認(rèn));  True 分布式 需要配置下方的 slaves
CLUSTER_ENABLE = True
配置名稱 意義 示例
SLAVES 【二選一】爬蟲機(jī)器配置列表 [{'host': '172.16.122.12', 'port': 22, 'user': 'spider', 'pwd': 'spider'}世分,
{'host': '172.16.122.13', 'port': 22, 'user': 'spider', 'pwd': 'spider'} ]
SLAVES_BALANCE 【二選一】爬蟲機(jī)器配置(ssh負(fù)載均衡) {'host': '172.16.122.11', 'port': 2202, 'user': 'spider', 'pwd': 'spider'}
SLAVES_ENV 【可選】爬蟲機(jī)器虛擬環(huán)境路徑 /home/spider/workspace/spiderman/venv
SLAVES_WORKSPACE 【必填】爬蟲機(jī)器代碼工程路徑 /home/spider/workspace/spiderman

如何管理爬蟲元數(shù)據(jù)

運(yùn)行 easy_meta.py 自動生成當(dāng)前項目所有爬蟲的元數(shù)據(jù), 默認(rèn)記錄到sqlite meta.db, 可以在 setting 中自行配置;

# 爬蟲 meta
META_ENGINE = 'sqlite:///meta.db'

元數(shù)據(jù)表meta字典如下:

字段名 類型 注釋
spider varchar(50) 爬蟲名
spider_comment varchar(100) 爬蟲描述
tb varchar(50) 表名
tb_comment varchar(100) 表描述
col_px int 字段序號
col varchar(50) 字段名
col_comment varchar(100) 字段描述
author varchar(20) 開發(fā)人員
addtime varchar(20) 開發(fā)時間
insertime varchar(20) 元數(shù)據(jù)更新時間

如何配合kafka做實(shí)時采集監(jiān)控

  1. 配置 kafka(修改 setting 的 KAFKA_SERVERS)
  2. 自定義監(jiān)控規(guī)則(修改編寫 kafka_mon.py , 并運(yùn)行該腳本程序, 開始監(jiān)控)
  3. 在 spider 中啟用 kafka 管道(運(yùn)行爬蟲 job , 開始采集)

如何使用爬蟲api

直接運(yùn)行 api.py,然后可以通過 http://127.0.0.1:2021/docs 查看相關(guān)的 api 文檔

注意事項

  1. 字段名稱不能使用 tablename缀辩、isload臭埋、ctime、bizdate臀玄、spider 等字段瓢阴,因為這些字段被作為通用字段,避免沖突
  2. items 文件每個字段建議添加注釋健无,生成元數(shù)據(jù)時荣恐,會將注釋導(dǎo)入到元數(shù)據(jù)表,便于管理爬蟲

hive環(huán)境問題

在 windows 環(huán)境下累贤,使用 python3 連接 hive 會有很多坑叠穆,所以使用 hdfs 管道時,hive 自動建表功能默認(rèn)關(guān)閉畦浓,便于部署痹束。
假如需要啟用 hive 自動建表功能,請進(jìn)行如下操作:

  1. pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
  2. pip install --no-deps thrift-sasl==0.2.1
  3. 驗證環(huán)境讶请,執(zhí)行 SP.utils.ctrl_hive

如果執(zhí)行成功祷嘶,說明 hive 環(huán)境準(zhǔn)備完畢屎媳,可以直接啟用 hive 自動建表功能;如果遇到問題论巍,可以參考 【大數(shù)據(jù)】windows 下python3連接hive

更新日志

日期 更新內(nèi)容
20200803 1.使用更優(yōu)雅的方式來生成元數(shù)據(jù);
2.管道函數(shù)傳參的寫法調(diào)整;
3.附件表通用字段更名:下載狀態(tài) (isload => status)
20200831 1.解決數(shù)據(jù)入庫失敗時烛谊,一直重試入庫的問題;
2.所有管道優(yōu)化,入庫失敗時嘉汰,自動切換成逐行入庫丹禀,只丟棄異常記錄
20201104 1.requests 中間件支持 DOWNLOAD_TIMEOUT、DOWNLOAD_DELAY
20201212 1.payload 中間件支持 DOWNLOAD_TIMEOUT鞋怀、DOWNLOAD_DELAY;
2.get_sp_cookies 方法優(yōu)化双泪,使用輕量級的 splash 替換 selenium;
3.md 的原理部分增加去重策略的說明
20210105 1.增加布隆過濾器
20210217 1.elasticsearch 管道調(diào)整,兼容 elasticsearch7 以上版本密似,直接使用表名作為索引名
20210314 1.所有反爬中間件合并到 SPMiddleWare
20210315 1.使用更優(yōu)雅的方式生成 job 初始請求;
2.headers 中間件優(yōu)化焙矛,減少 redis 的內(nèi)存占用;
3.刪除 cookie 中間件,cookie 只是 headers 里面的一個值残腌,可以直接使用 headers 中間件;
4.刪除 Payload 中間件村斟,Payload 請求可以直接使用 requests 中間件
5.增加 CookiesPool 中間件,用于需要多個賬號隨機(jī)切換采集的場景
20210317 1.增加可以脫離 scrapy 獨(dú)立工作的抛猫、支持分布式的附件下載器
20210318 1.增加 api 服務(wù)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蟆盹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子闺金,更是在濱河造成了極大的恐慌逾滥,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掖看,死亡現(xiàn)場離奇詭異匣距,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)哎壳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門毅待,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人归榕,你說我怎么就攤上這事尸红。” “怎么了刹泄?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵外里,是天一觀的道長。 經(jīng)常有香客問我特石,道長盅蝗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任姆蘸,我火速辦了婚禮墩莫,結(jié)果婚禮上芙委,老公的妹妹穿的比我還像新娘。我一直安慰自己狂秦,他們只是感情好灌侣,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著裂问,像睡著了一般侧啼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上堪簿,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天痊乾,我揣著相機(jī)與錄音,去河邊找鬼戴甩。 笑死符喝,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的甜孤。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼畏腕,長吁一口氣:“原來是場噩夢啊……” “哼缴川!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起描馅,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤把夸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后铭污,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恋日,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年嘹狞,在試婚紗的時候發(fā)現(xiàn)自己被綠了岂膳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡磅网,死狀恐怖谈截,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涧偷,我是刑警寧澤簸喂,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站燎潮,受9級特大地震影響喻鳄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜确封,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一除呵、第九天 我趴在偏房一處隱蔽的房頂上張望再菊。 院中可真熱鬧,春花似錦竿奏、人聲如沸袄简。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绿语。三九已至,卻和暖如春候址,著一層夾襖步出監(jiān)牢的瞬間吕粹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工岗仑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留匹耕,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓荠雕,卻偏偏與公主長得像稳其,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子炸卑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容