Python 3.6 抓取微博m站數據
2019.05.01 更新內容
- containerid 可以通過
"107603" + user_id組裝得到,無需請求個人信息獲取; - 優化多線程抓取,修復之前因
urllib.request全局定義,導致代理無法正常切回本地IP; - 優化分布式抓取策略,由每台機器順序獲取用戶ID 再拼裝URL抓取策略,修改為每台機器順序獲取URL進行抓取。防止由於某個微博賬號微博動態過多導致負責本ID的機器長時間運行,而其他機器就要等待,浪費時間和資源。
- 加入IP代理池維護腳本,可以定時維護代理池中的有效代理IP,及時剔除無效IP。
- 加入Redis定時消費腳本,解決因抓取結果過大導致redis性能下降。
- 增加Redis連接池
ConnectionPool,解決因Redis鏈接端口數過多導致Redis拒絕服務錯誤。 - 調整Redis數據存儲結構,采用list+set結合,存儲UID+URL
- 單機https代理消費約100元/天,單機5個進程+代理每天能達到1000萬條數據
本腳本截止20190501
- 網址: https://m.weibo.cn/u/5463009082 新浪微博m站(智能手機網頁端)
- api : https://m.weibo.cn/api/container/getIndex?type=uid&value=5463009082&containerid=1076035463009082
- 抓取: 根據用戶userId抓取歷史發布的微博信息
- 方法: python請求api接口(非頁面)
- 反扒: 瘋狂抓取10-20s,IP會被禁封1-3分鍾 或者 抓取2分鍾禁封10分鍾
- 備注: 無需登錄+IP代理池
- 環境: Windosw或Linux、Python 3.6、Mysql、Redis
| 類型 | 效果 | 代理花費 |
|---|---|---|
| 單機版(多線程+多進程) | 150萬/天 | 0 |
| 單機版(多線程+多進程)+IP代理池 | 1000萬/天 | 100元/天 |
| 分布式(多線程+多進程)+IP代理池 | 千萬~億級 | 100*機器數量/天 |
抓取流程
-
啟動
save_uid.py腳本將准備好的微博用戶ID,存入Redis中,保存兩份;r.lpush(WEIBO_UID_LIST_KEY, uid)用於第一次遍歷UID請求每個UID的總頁數,然后生成每個UID的所有URL。r.sadd(WEIBO_UID_SET_KEY, uid)用於第二次請求,隨機獲取一個未抓取完的UID,去Redis中取當前UID剩余的URL進行抓取,全部抓取完畢則移除此UID。
-
啟動
proxy_pool.py腳本,初始化IP代理池(如果不使用代理,此步驟可略過)target_money用來獲取你所購買的IP代理剩余金額的URL連接target_ip請求代理IP獲取有效的代理IPtargetUrl用來校驗當前IP是否有效WEIBO_PROXY_SET_KEY存儲有效的代理IPWEIBO_PROXY_418_SET_KEY存儲已經出現418錯誤的IP,會循環利用,直到代理失效WEIBO_ERROR_PROXY_SET_KEY存儲已經使用過的IP(失效IP),用於后期校驗
-
啟動
start_crawler.py腳本,開啟抓取任務- 首先會第一次請求遍歷UID,生成所有的URL,然后所有的線程獲取URL進行抓取
- 先會嘗試使用本地IP進行抓取,本地IP出現418之后,嘗試去IP代理池獲取可使用的IP,繼續抓取
- 使用代理IP抓取超過60s,停止代理抓取改為使用本地IP,循環進行
- 代理IP出現418,則先去嘗試使用本地IP,如果本地418再繼續更換代理
- 如果代理池沒有可用IP,則休息30s,繼續使用本地IP
-
添加Linux定時腳本,定時處理Redis隊列中的抓取結果。
關於代理IP
- 抓取微博的https連接,只能使用https代理,可選擇市面上其他類型的代理商;
- 免費的代理ip也有嘗試,不過效果不是很好
部署問題
- 需要一台主服務器(或者本機Windows電腦)來初始化運行
save_uid.py和proxy_pool.py腳本 - 在Redis所在的服務器進行
redis_consumer.py腳本的運行部署 start_crawler.py可以集群部署到多台服務器,但要保證都能網絡連通到Redis服務器- 添加定時腳本
crontab -e內容 如下0 */1 * * * nohup python /data/hw/redis_consume.py > /dev/null 2>&1 & service cron restart重啟cron定時服務- 創建start.sh 開啟多進程抓取
#!/bin/bash # 開始爬蟲程序; for((i=1;i<=5;i++)); do nohup python /data/hw/start_crawler.py 1>/dev/null 2>&1 & echo "開啟爬蟲程序進程"+$i done sleep 5s echo "已開啟以下進程" ps -ef|grep python
20190501目錄
- proxy_pool.py #維護IP代理池
- redis_consume.py #redis定時消費
- save_uid.py #初始化uid
- start.sh #一鍵啟動腳本
- start_crawler.py #開啟抓取程序,可以集群部署
