前言
本文的文字及圖片來源于網路,僅供學習、交流使用,不具有任何商業用途,著作權歸原作者所有,如有問題請及時聯系我們以作處理,
作者:徐洲更
為了實作該爬蟲我們需要用到如下工具
- Chrome瀏覽器
- Python 3 語法知識
- Python的Requests庫
此外,這個爬取程式利用的是微信公眾號后臺編輯素材界面,原理是,當我們在插入超鏈接時,微信會呼叫專門的API(見下圖),以獲取指定公眾號的文章串列,因此,我們還需要有一個公眾號,
PS:如有需要Python學習資料的小伙伴可以加下方的群去找免費管理員領取
可以免費領取原始碼、專案實戰視頻、PDF檔案等
正式開始
我們需要登錄微信公眾號,點擊素材管理,點擊新建圖文訊息,然后點擊上方的超鏈接,
接著,按F12,打開Chrome的開發者工具,選擇Network
此時在之前的超鏈接界面中,點擊「選擇其他公眾號」,輸入你需要爬取的公眾號(例如中國移動)
此時之前的Network就會重繪出一些鏈接,其中以"appmsg"開頭的便是我們需要分析的內容
我們決議請求的URL
https://mp.weixin.qq.com/cgi-bin/appmsg?action=list_ex&begin=0&count=5&fakeid=MzI1MjU5MjMzNA==&type=9&query=&token=143406284&lang=zh_CN&f=json&ajax=1
它分為三個部分
- https://mp.weixin.qq.com/cgi-bin/appmsg: 請求的基礎部分
- ?action=list_ex: 常用于動態網站,實作不同的引數值而生成不同的頁面或者回傳不同的結果
- &begin=0&count=5&fakeid: 用于設定?里的引數,即begin=0, count=5
通過不斷的瀏覽下一頁,我們發現每次只有begin會發生變動,每次增加5,也就是count的值,
接著,我們通過Python來獲取同樣的資源,但直接運行如下代碼是無法獲取資源的
import requests url = "https://mp.weixin.qq.com/cgi-bin/appmsg?action=list_ex&begin=0&count=5&fakeid=MzI1MjU5MjMzNA==&type=9&query=&token=1957521839&lang=zh_CN&f=json&ajax=1" requests.get(url).json() # {'base_resp': {'ret': 200003, 'err_msg': 'invalid session'}}
我們之所以能在瀏覽器上獲取資源,是因為我們登錄了微信公眾號后端,而Python并沒有我們的登錄資訊,所以請求是無效的,我們需要在requests中設定headers引數,在其中傳入Cookie和User-Agent,來模擬登陸
由于每次頭資訊內容都會變動,因此我將這些內容放入在單獨的檔案中,即"wechat.yaml",資訊如下
cookie: ua_id=wuzWM9FKE14...
user_agent: Mozilla/5.0...
之后只需要讀取即可
# 讀取cookie和user_agent import yaml with open("wechat.yaml", "r") as file: file_data = file.read() config = yaml.safe_load(file_data) headers = { "Cookie": config['cookie'], "User-Agent": config['user_agent'] } requests.get(url, headers=headers, verify=False).json()
在回傳的JSON中,我們就看到了每個文章的標題(title), 摘要(digest), 鏈接(link), 推送時間(update_time)和封面地址(cover)等資訊,
appmsgid是每一次推送的唯一識別符號,aid則是每篇推文的唯一識別符號,
實際上,除了Cookie外,URL中的token引數也會用來限制爬蟲,因此上述代碼很有可能輸出會是{'base_resp': {'ret': 200040, 'err_msg': 'invalid csrf token'}}
接著我們寫一個回圈,獲取所有文章的JSON,并進行保存,
import json import requests import time import random import yaml with open("wechat.yaml", "r") as file: file_data = file.read() config = yaml.safe_load(file_data) headers = { "Cookie": config['cookie'], "User-Agent": config['user_agent'] } # 請求引數 url = "https://mp.weixin.qq.com/cgi-bin/appmsg" begin = "0" params = { "action": "list_ex", "begin": begin, "count": "5", "fakeid": config['fakeid'], "type": "9", "token": config['token'], "lang": "zh_CN", "f": "json", "ajax": "1" } # 存放結果 app_msg_list = [] # 在不知道公眾號有多少文章的情況下,使用while陳述句 # 也方便重新運行時設定頁數 i = 0 while True: begin = i * 5 params["begin"] = str(begin) # 隨機暫停幾秒,避免過快的請求導致過快的被查到 time.sleep(random.randint(1,10)) resp = requests.get(url, headers=headers, params = params, verify=False) # 微信流量控制, 退出 if resp.json()['base_resp']['ret'] == 200013: print("frequencey control, stop at {}".format(str(begin))) break # 如果回傳的內容中為空則結束 if len(resp.json()['app_msg_list']) == 0: print("all ariticle parsed") break app_msg_list.append(resp.json()) # 翻頁 i += 1
在上面代碼中,我將fakeid和token也存放在了"wechat.yaml"檔案中,這是因為fakeid是每個公眾號都特有的識別符號,而token則會經常性變動,該資訊既可以通過決議URL獲取,也可以從開發者工具中查看
在爬取一段時間后,就會遇到如下的問題
{'base_resp': {'err_msg': 'freq control', 'ret': 200013}}
此時你在公眾號后臺嘗試插入超鏈接時就能遇到如下這個提示
這是公眾號的流量限制,通常需要等上30-60分鐘才能繼續,為了完美處理這個問題,你可能需要申請多個公眾號,可能需要和微信公眾號的登錄系統斗智斗勇,或許還需要設定代理池,
但是我并不需要一個工業級別的爬蟲,只想爬取自己公眾號的資訊,因此等個一小時,重新登錄公眾號,獲取cookie和token,然后運行即可,我可不想用自己的興趣挑戰別人的飯碗,
最后將結果以JSON格式保存,
# 保存結果為JSON json_name = "mp_data_{}.json".format(str(begin)) with open(json_name, "w") as file: file.write(json.dumps(app_msg_list, indent=2, ensure_ascii=False))
或者提取文章識別符號,標題,URL,發布時間這四列資訊,保存成CSV,
info_list = [] for msg in app_msg_list: if "app_msg_list" in msg: for item in msg["app_msg_list"]: info = '"{}","{}","{}","{}"'.format(str(item["aid"]), item['title'], item['link'], str(item['create_time'])) info_list.append(info) # save as csv with open("app_msg_list.csv", "w") as file: file.writelines("\n".join(info_list))
下一篇,將介紹如何根據每個文章的連接地址,來獲取每篇文章的閱讀量資訊,
參考資料
https://blog.csdn.net/kindred_joe/article/details/99289890
https://blog.csdn.net/qq_28804275/article/details/82150874
最終代碼如下(代碼可能有bug,謹慎使用),使用方法為python wechat_parser.py wechat.yaml
import json import requests import time import random import os import yaml import sys if len(sys.argv) < 2: print("too few arguments") sys.exit(1) yaml_file = sys.argv[1] if not os.path.exists(yaml_file): print("yaml_file is not exists") sys.exit(1) with open(yaml_file, "r") as file: file_data = file.read() config = yaml.safe_load(file_data) headers = { "Cookie": config['cookie'], "User-Agent": config['user_agent'] } # 請求引數 url = "https://mp.weixin.qq.com/cgi-bin/appmsg" begin = "0" params = { "action": "list_ex", "begin": begin, "count": "5", "fakeid": config['fakeid'], "type": "9", "token": config['token'], "lang": "zh_CN", "f": "json", "ajax": "1" } # 存放結果 if os.path.exists("mp_data.json"): with open("mp_data.json", "r") as file: app_msg_list = json.load(file) else: app_msg_list = [] # 在不知道公眾號有多少文章的情況下,使用while陳述句 # 也方便重新運行時設定頁數 i = len(app_msg_list) while True: begin = i * 5 params["begin"] = str(begin) # 隨機暫停幾秒,避免過快的請求導致過快的被查到 time.sleep(random.randint(1,10)) resp = requests.get(url, headers=headers, params = params, verify=False) # 微信流量控制, 退出 if resp.json()['base_resp']['ret'] == 200013: print("frequencey control, stop at {}".format(str(begin))) break # 如果回傳的內容中為空則結束 if len(resp.json()['app_msg_list']) == 0: print("all ariticle parsed") break app_msg_list.append(resp.json()) # 翻頁 i += 1 # 保存結果為JSON json_name = "mp_data.json" with open(json_name, "w") as file: file.write(json.dumps(app_msg_list, indent=2, ensure_ascii=False))
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/24492.html
標籤:Python
上一篇:Python爬蟲實體-多執行緒爬蟲糗事百科搞笑內涵段子
下一篇:419遞增子序列
