1. 程式人生 > 實用技巧 >Python3 爬蟲工作的一些總結

Python3 爬蟲工作的一些總結

閒著沒事,我也寫一下我自己用到的一些最簡單的爬蟲所需的技術和工具,以後可能就不想寫爬蟲了,畢竟爬蟲深似海!哎?,也為自己做一個筆記,如果能幫到部分爬蟲新手的話就更好了
下圖是我在看到的一幅圖片,說出了我的心聲,獻給入爬蟲坑的新手們。

而且現在基本都是抓取APP資料,說簡單也簡單,說難是真TMD難!!
簡單:
app的資料比web端資料更容易抓取,基本都是http、https協議,返回的資料格式也相對規整,
大多是json格式
困難:
1.需要反編譯的知識,需要分析加密演算法
2.需要脫殼+反編譯
3.需要破解各式各類的簽名,證書.
所以一個爬蟲工程師慢慢就需要掌握以下技能:
java程式設計基礎
android程式設計基礎
app逆向
app脫殼
破解加密
....
從入門到全棧?
最最最重要的!!!
爬蟲崗位一般都是公司邊緣化崗位,而且崗位也不多,所以工資什麼的,明白了吧,能不轉爬蟲就別轉爬蟲吧。

文章目錄

  • 後續有時間補上

正則篇

  • 因為我是用爬蟲來抓取文章的,一般就是提取文章資料,或者去除下標籤之類的,順便說一下我這幾步正則只對標籤做處理,沒有處理到任何文字, 當然style樣式除外。

需求一: 要求文章只需要儲存p和img標籤,其他標籤全部都去掉
需求二: 去掉p標籤和img標籤的其他style樣式,當然我那個img標籤裡面的圖片src是上傳到七牛雲上面的。
當然如果讀者 有其他需求的正則,我有空也可以幫忙寫一下

# 去掉除了p標籤和Img標籤之外的其他標籤
import re
content = """<div class="__reader_view_article_wrap_694501494498835__"><div class="pgc-img"><img src="http://p3.pstatp.com/large/pgc-image/adc1249ecb3140ec8e7037f37014c795" img_width="708" img_height="145" alt="ofo破產?官方宣告來了!" inline="0"><p class="pgc-img-caption"></p></div><blockquote><p>ofo迴應破產傳聞:訊息嚴重不實,目前運營一切正常。此前新京報稱,ofo運營主體拜克洛克首次現身全國...</p></blockquote><p class="ql-align-justify">本文來自全天候科技,閱讀更多請登陸www.awtmt.com或華爾街見聞APP。</p><p class="ql-align-justify">4月2日,全國企業破產重整案件資訊網顯示,ofo運營主體之一北京拜克洛克科技有限公司作為“被申請人”而出現,申請人為聶豔,日期是3月25日,辦理法院為北京海淀區人民法院。多家媒體質疑ofo是否陷入破產危機。</p><p class="ql-align-justify">下午,ofo迴應破產傳聞:訊息嚴重不實,目前運營一切正常。此前新京報稱,ofo運營主體拜克洛克首次現身全國破產資訊網。</p><div class="pgc-img"><img src="http://p1.pstatp.com/large/pgc-image/84657696ee424b6399b4a5a992188d04" img_width="1080" img_height="1920" alt="ofo破產?官方宣告來了!" inline="0"><p class="pgc-img-caption"></p></div><p class="ql-align-justify">在此宣告之前,ofo一直處於輿論的風口浪尖,從明星創業公司到瀕臨破產,ofo快速經歷了這一切過程。</p><h1 class="ql-align-center">退押金風波</h1><p class="ql-align-justify">2018年12月中旬,ofo待退押金總額一再重新整理。據全天候科技獲悉,截至12月18日20時37分,排隊退押使用者數突破1000萬。</p><p class="ql-align-justify">ofo使用者押金主要有99元與199元兩種。如果以99元/位計算,保守估計,ofo需退還押金總額約10億元;但若以199元/位計算,那麼ofo需要退還高達近20億元的押金。</p><div class="pgc-img"><img src="http://p3.pstatp.com/large/pgc-image/7c9fbdb6c3d1484d833cbfc4d55ad406" img_width="438" img_height="529" alt="ofo破產?官方宣告來了!" inline="0"><p class="pgc-img-caption">圖片來源:網路</p></div><p class="ql-align-justify"> 資料仍在不斷增加,有不少ofo使用者被曝前往ofo北京總部(位於北京中關村的網際網路金融中心)尋求退押金,現場排起了長隊。</p><p class="ql-align-justify">ofo方面於去年12月17日晚推出新政:自2018年12月18日起,凡在App內提交線上申請退押金的使用者,後臺系統會根據申請提交的順序進行相關資訊稽核與收集,核實完畢後用戶將進入退押金序列,ofo將按順序退款;如有線下登記的使用者此前已經發起退款申請,則按此前的佇列時間資訊為準。</p><p class="ql-align-justify">ofo小黃車還提醒:由於使用者基數大,存在退押金申請激增的可能。同時,ofo承諾依序妥善處理好退押金事宜。</p><p class="ql-align-justify">雖然做出了相關承諾,退押工作也在逐步推進,但使用者仍憂心忡忡,擔心萬一ofo破產後拿不到押金。</p><h1 class="ql-align-center">招募區域化加盟代理商</h1><p class="ql-align-justify">為了給ofo續命化解經營危機,戴威也開始使用新的營銷手段,比如招募ofo代理商。</p><p class="ql-align-justify">據鈦媒體,ofo城市代理運營商主要負責轄區內ofo共享單車的運營業務,單車所有權仍歸屬於ofo公司,代理運營商只負責單車的維修、秩序維護等,ofo按照後臺資料來結算費用。</p><p class="ql-align-justify">也就是說,ofo把原本屬於各地分公司維護單車的任務外包了,負責維護的不再是自己員工,而是各地招募的代理商,此舉可降低共享單車運營成本。</p><p class="ql-align-justify">為號召更多代理商加入,ofo宣稱共享單車代理商已經成為一個新的熱門行業。日前,據接近ofo內部人士透露,ofo今年將大範圍向全國三、四線城市推廣代理模式,此前,ofo曾在山東威海、泰安等城市試執行“代理”模式,而在代理商模式之前,ofo嘗試過合夥人、直營+代理等模式,效果均不甚理想。如今,ofo小黃車遭遇前所未有的資金鍊危機,採取降低成本的運營方案就不難理解。</p><p class="ql-align-justify">ofo國內運營事業部總經理<span>周偉國</span>對此表示:“ofo進入精細化運營階段,代理模式可將本土企業與行業巨頭有效對接,既可實現引領行業快速發展,又能實現本土資源效率使用最大化,以最低的成本實現多贏發展。”</p><p class="ql-align-justify">此前,為給ofo續命,公司已不斷開源節流,如在App上推出短視訊廣告,使用者掃碼騎行前需要觀看短視訊;比如官方微信公眾號接受廣告投放,甚至售賣三無蜂蜜並被人詬病;甚至為了免付使用者押金而計劃把使用者導流給網貸企業,在正式推送後當天即宣告下線。</p><p class="ql-align-justify">而在宣佈二三線城市開啟代理運營商模式的前一天,ofo官方通報公司的反腐情況。經調查,ofo內部總共發生了8起腐敗案件,其中4起已進入司法程式,5人被移送司法機關,涉案金額達數百萬元,ofo也在積極追回賬款。</p><p class="ql-align-justify">雖然使出渾身解數開源節流,但ofo是否能真的走出破產危機尚不太樂觀。</p></div>"""
content = re.sub(r"<(?!/?\s?p|/?\s?img)[^<>]*>", "", content)   // 反向選擇 去掉除了p和img之外的其他標籤,可以在 | 後面在新增其他反向條件
content = re.sub(r"<p[\s\S]*?>", r"<p>", content)   // 替換p標籤裡面的style樣式
# 分組替換 掉img標籤裡面的style樣式, 但是保留img裡面的src屬性
# content = re.sub(r"<img[\s\S]*?src=[\"|\'](?P<src>[\s\S]*?)[\"|\'][\s\S]*?>", r"<img src=‘\g<src>’>", content)   # 方式一 這種是匹配src的連結
content = re.sub(r"<img[\s\S]*?(?P<src>src=[\"|\'][\s\S]*?[\"|\'])[\s\S]*?>", r"<img \g<src> >", content)   # 方式二  匹配整個src   \g是獲取前面分組命名的固定寫法
print(content)  
# 說個小技巧吧,應該大部分都知道,正則匹配的時候,可以先用repr(temp_str) 檢視原始資料。  
# 輸出  
"""<img src="http://p3.pstatp.com/large/pgc-image/adc1249ecb3140ec8e7037f37014c795" ><p></p><p>ofo迴應破產傳聞:訊息嚴重不實,目前運營一切正常。此前新京報稱,ofo運營主體拜克洛克首次現身全國...</p><p>本文來自全天候科技,閱讀更多請登陸www.awtmt.com或華爾街見聞APP。</p><p>4月2日,全國企業破產重整案件資訊網顯示,ofo運營主體之一北京拜克洛克科技有限公司作為“被申請人”而出現,申請人為聶豔,日期是3月25日,辦理法院為北京海淀區人民法院。多家媒體質疑ofo是否陷入破產危機。</p><p>下午,ofo迴應破產傳聞:訊息嚴重不實,目前運營一切正常。此前新京報稱,ofo運營主體拜克洛克首次現身全國破產資訊網。</p><img src="http://p1.pstatp.com/large/pgc-image/84657696ee424b6399b4a5a992188d04" ><p></p><p>在此宣告之前,ofo一直處於輿論的風口浪尖,從明星創業公司到瀕臨破產,ofo快速經歷了這一切過程。</p>退押金風波<p>2018年12月中旬,ofo待退押金總額一再重新整理。據全天候科技獲悉,截至12月18日20時37分,排隊退押使用者數突破1000萬。</p><p>ofo使用者押金主要有99元與199元兩種。如果以99元/位計算,保守估計,ofo需退還押金總額約10億元;但若以199元/位計算,那麼ofo需要退還高達近20億元的押金。</p><img src="http://p3.pstatp.com/large/pgc-image/7c9fbdb6c3d1484d833cbfc4d55ad406" ><p>圖片來源:網路</p><p> 資料仍在不斷增加,有不少ofo使用者被曝前往ofo北京總部(位於北京中關村的網際網路金融中心)尋求退押金,現場排起了長隊。</p><p>ofo方面於去年12月17日晚推出新政:自2018年12月18日起,凡在App內提交線上申請退押金的使用者,後臺系統會根據申請提交的順序進行相關資訊稽核與收集,核實完畢後用戶將進入退押金序列,ofo將按順序退款;如有線下登記的使用者此前已經發起退款申請,則按此前的佇列時間資訊為準。</p><p>ofo小黃車還提醒:由於使用者基數大,存在退押金申請激增的可能。同時,ofo承諾依序妥善處理好退押金事宜。</p><p>雖然做出了相關承諾,退押工作也在逐步推進,但使用者仍憂心忡忡,擔心萬一ofo破產後拿不到押金。</p>招募區域化加盟代理商<p>為了給ofo續命化解經營危機,戴威也開始使用新的營銷手段,比如招募ofo代理商。</p><p>據鈦媒體,ofo城市代理運營商主要負責轄區內ofo共享單車的運營業務,單車所有權仍歸屬於ofo公司,代理運營商只負責單車的維修、秩序維護等,ofo按照後臺資料來結算費用。</p><p>也就是說,ofo把原本屬於各地分公司維護單車的任務外包了,負責維護的不再是自己員工,而是各地招募的代理商,此舉可降低共享單車運營成本。</p><p>為號召更多代理商加入,ofo宣稱共享單車代理商已經成為一個新的熱門行業。日前,據接近ofo內部人士透露,ofo今年將大範圍向全國三、四線城市推廣代理模式,此前,ofo曾在山東威海、泰安等城市試執行“代理”模式,而在代理商模式之前,ofo嘗試過合夥人、直營+代理等模式,效果均不甚理想。如今,ofo小黃車遭遇前所未有的資金鍊危機,採取降低成本的運營方案就不難理解。</p><p>ofo國內運營事業部總經理周偉國對此表示:“ofo進入精細化運營階段,代理模式可將本土企業與行業巨頭有效對接,既可實現引領行業快速發展,又能實現本土資源效率使用最大化,以最低的成本實現多贏發展。”</p><p>此前,為給ofo續命,公司已不斷開源節流,如在App上推出短視訊廣告,使用者掃碼騎行前需要觀看短視訊;比如官方微信公眾號接受廣告投放,甚至售賣三無蜂蜜並被人詬病;甚至為了免付使用者押金而計劃把使用者導流給網貸企業,在正式推送後當天即宣告下線。</p><p>而在宣佈二三線城市開啟代理運營商模式的前一天,ofo官方通報公司的反腐情況。經調查,ofo內部總共發生了8起腐敗案件,其中4起已進入司法程式,5人被移送司法機關,涉案金額達數百萬元,ofo也在積極追回賬款。</p><p>雖然使出渾身解數開源節流,但ofo是否能真的走出破產危機尚不太樂觀。</p>"""

說個很方便的小技巧, 需要用到sublime編輯工具, (ps:在慕課網上學的)
比如爬蟲會攜帶一大堆請求頭資料,直接複製別人的header 需要自己手動一個個新增引號
1 開啟sublime
2 貼上請求頭
3 按ctrl+h 組合鍵 注意需要開啟正則模式才行 點選 .* 開啟
4 點選 replace all 就好了

(.*?):\s(.*)      # Find  
"$1": "$2",     # Replace


轉換之後就是這樣的 不用手動新增引號 特別方便

簡單圖片識別

1 使用pytesseract 庫簡單圖片識別 (不推薦,推薦使用下面那一種),

這種效果不是很好,複雜的情況建議直接打碼平臺。
注意

:安裝的時候有些小坑, 而且 chi_sim中文識別,這個庫需要去github 上面下載地址。

from PIL import Image
import pytesseract
# 方式一 處理本地圖片
im = Image.open("./aaa.png")
text = pytesseract.image_to_string(im, lang='chi_sim')   # 處理圖片 lang是選擇的語言,預設識別英文和數字
# 具體安裝執行 可能有些坑, 
print(text)
# --------------------------------------------------
# 方式二 處理url圖片位元組流
import io
img2 = requests.get(url, headers=headers, stream=True)
byte_stream = io.BytesIO(img2.content)
img2_str = pytesseract.image_to_string(Image.open(byte_stream))
print(img2_str)
2 使用muggle_ocr庫簡單的驗證碼識別(推薦你用這個)

,效果比上面一種效率高,使用更方便,會自動安裝tensorflow numpy這兩個依賴庫;
pip install muggle-ocr
https://pypi.org/project/muggle-ocr/

import time

# 1. 匯入包
import muggle_ocr

"""
使用預置模型,預置模型包含了[ModelType.OCR, ModelType.Captcha] 兩種
其中 ModelType.OCR 用於識別普通印刷文字, ModelType.Captcha 用於識別4-6位簡單英數驗證碼

"""

# 開啟印刷文字圖片
with open(r"test1.png", "rb") as f:
    ocr_bytes = f.read()

# 開啟驗證碼圖片
with open(r"test2.jpg", "rb") as f:
    captcha_bytes = f.read()

# 2. 初始化;model_type 可選: [ModelType.OCR, ModelType.Captcha]
sdk = muggle_ocr.SDK(model_type=muggle_ocr.ModelType.OCR)

# ModelType.Captcha 可識別光學印刷文字
for i in range(5):
    st = time.time()
    # 3. 呼叫預測函式
    text = sdk.predict(image_bytes=ocr_bytes)
    print(text, time.time() - st)

# ModelType.Captcha 可識別4-6位驗證碼
sdk = muggle_ocr.SDK(model_type=muggle_ocr.ModelType.Captcha)
for i in range(5):
    st = time.time()
    # 3. 呼叫預測函式
    text = sdk.predict(image_bytes=captcha_bytes)
    print(text, time.time() - st)

"""
使用自定義模型
支援基於 https://github.com/kerlomz/captcha_trainer 框架訓練的模型
訓練完成後,進入匯出編譯模型的[out]路徑下, 把[graph]路徑下的pb模型和[model]下的yaml配置檔案放到同一路徑下。
將 conf_path 引數指定為 yaml配置檔案 的絕對或專案相對路徑即可,其他步驟一致,如下示例:
"""
with open(r"test3.jpg", "rb") as f:
    b = f.read()
sdk = muggle_ocr.SDK(conf_path="./ocr.yaml")
text = sdk.predict(image_bytes=b)

檢測代理IP是否有效

代理IP,每個爬蟲人員多少都會用到一點的,檢測代理IP的方式也有很多種,這只是其中之一

import telnetlib

# 連線Telnet伺服器
try:
	# 引數說明                   ip             埠        超時時間 
    tn = telnetlib.Telnet('115.227.159.73', port='4312', timeout=10)   
except Exception as e:
    print('失敗', e)
else:
    print('成功')

Linux 定時任務篇

有時候我需要去定時之前的爬蟲資料。
定時任務在Ubuntu系發行版和 Cetntos繫上,操作稍微有點不一樣, 總體是一樣的。
定時任務的重要性,引用下下面網站的一句話:Cron job failures can be disastrous!

crontab -e   # 進入定時任務編輯介面
# 就可以進入編輯介面 用法和Vi編輯器差不多  # Ubuntu上或許第一進入會讓你選擇用什麼編輯器 我現在只記得選擇的第三種
# 可以寫你的定時任務指令碼了 
# 可參考 https://crontab.guru/
ctrl+O  # 回車 Enter 確認定時任務檔名
ctrl+X  # 儲存退出

# 寫完之後 最好重啟下
寫完一個定時任務命令之後需要重啟,下面是相關的操作語句。
注意不同發行版的不同 參考連結  https://www.cyberciti.biz/faq/howto-linux-unix-start-restart-cron/
# Debian/Ubuntu/Linux EXamples:
sudo service cron status   
sudo service cron stop
sudo service cron start
sudo service cron restart
# RHEL/CentOS/Fedor Linux:
service crond status
service crond stop
service crond start
service crond restart

如果報:Redirecting to /bin/systemctl start  crond.service
估計是使用的是Centos7或者Fedora高版本,啟用服務變化了。
就執行:
systemctl restart crond.service
# 檢視你現在正在執行中的定時任務
crontab -l

Linux後臺執行Python檔案

有時候,寫了一些小指令碼,就一個py檔案寫的,需要丟到伺服器讓它慢慢跑,這時就需要後臺運行了,然後關於命令 2>&1的解釋,我搜了下StackOverflow上面的解釋 ,有興趣可以瞭解瞭解https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean 如果這個網站訪問慢打不開,參考我之前轉載部落格可以解決。

# nohup 命令可能需要安裝
# 後臺執行  表示不掛起(no hang up)  使用-u引數,使得python不啟用緩衝
nohup python -u test.py > test.log 2>&1 &

另外補充一個,kill指定埠的命令()

# kill 佔用埠號為8080的程式
kill -9 `lsof -t -i:8080`

關於 requests 庫的操作

  • cookies的用法
# 使用cookie的話,我就推薦用requests的姊妹庫requests_html, 對cookie操作更友好
from requests_html import HTMLSession
session = HTMLSession()  # 使用方法和requests一樣(因為都是kennethreitz寫的)
res = session.get("http://www.baidu.com")
dict_current_cookie = session.cookies.get_dict()   # dict型別的cookie
print(dict_current_cookie)  # 可以把cookie儲存到redis之類的地方

# 載入使用 cookie 我是使用的這種笨辦法, 重新把格式重組的
old_cookie = ";".join([f"{i}={dict_current_cookie[i]}" for i in dict_current_cookie])

s = session.get(example_url, cookies=old_cookie)
  • 請求媒體資原始檔,比如小視訊,音樂,圖片等
import requests
 
with requests.get("http://xxx.xxx.com/xxxx.mp4", stream=True) as req:
    with open("./test_name.mp4", "wb+") as f:
        f.write(req.content)

驗證requests http請求

比如驗證代理,請求頭是否有效, 可以使用這個網站 https://httpbin.org

GET請求驗證 https://httpbin.org/get

import requests
headers = {
   "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36",
}
proxies = {
    "http": "http://115.207.115.83:4376",
    "https": "http://115.207.115.83:4376"
}
url = "https://httpbin.org/get"
resp = requests.get(url, headers=headers, proxies=proxies)
print(resp.status_code)
print(resp.text)

輸出

200
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36", 
    "X-Amzn-Trace-Id": "Root=1-5fd426e7-68c54eb72581379373f3038b"
  }, 
  "origin": "115.207.115.83", 
  "url": "https://httpbin.org/get"
}

POST請求測試 https://httpbin.org/post

url = "https://httpbin.org/post"
json_data = {
    "qqq": ["1111", "222"],
    "www": {"qq": "zz"}
}
resp = requests.post(url, json=json_data, headers=headers)
print(resp.json())

返回

{
  "args": {}, 
  "data": "{\"qqq\": [\"1111\", \"222\"], \"www\": {\"qq\": \"zz\"}}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "45", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36", 
    "X-Amzn-Trace-Id": "Root=1-5fd429b1-75fd90d55f44a03653698acc"
  }, 
  "json": {
    "qqq": [
      "1111", 
      "222"
    ], 
    "www": {
      "qq": "zz"
    }
  }, 
  "origin": "你的IP", 
  "url": "https://httpbin.org/post"
}


  • 未完待續....