微信公眾號后臺編輯素材界面的原理和原理
優(yōu)采云 發(fā)布時(shí)間: 2021-07-26 22:05微信公眾號后臺編輯素材界面的原理和原理
準備階段
為了實(shí)現這個(gè)爬蟲(chóng),我們需要使用以下工具
另外,這個(gè)爬蟲(chóng)程序使用了微信公眾號后臺編輯素材接口。原理是當我們插入超鏈接時(shí),微信會(huì )調用一個(gè)特殊的API(見(jiàn)下圖)來(lái)獲取指定公眾號的文章列表。因此,我們還需要有一個(gè)官方帳號。
fig1 正式啟動(dòng)
我們需要登錄微信公眾號,點(diǎn)擊素材管理,點(diǎn)擊新建圖文消息,然后點(diǎn)擊上面的超鏈接。
圖2
接下來(lái),按 F12,打開(kāi) Chrome 的開(kāi)發(fā)者工具,然后選擇網(wǎng)絡(luò )
圖3
此時(shí),在之前的超鏈接界面,點(diǎn)擊“選擇其他公眾號”,輸入你需要抓取的公眾號(例如中國移動(dòng))
圖4
這時(shí)候之前的Network會(huì )刷新一些鏈接,其中“appmsg”開(kāi)頭的內容就是我們需要分析的
圖5
我們解析請求的 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
分為三個(gè)部分
通過(guò)不斷瀏覽下一頁(yè),我們發(fā)現每次只有begin會(huì )改變,每次增加5,這就是count的值。
接下來(lái)我們使用Python獲取同樣的資源,但是直接運行下面的代碼是無(wú)法獲取資源的。
import requestsurl = "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沒(méi)有我們的登錄信息,所以請求無(wú)效。我們需要在requests中設置headers參數,并傳入Cookie和User-Agent來(lái)模擬登錄
由于頭信息的內容每次都會(huì )變化,所以我把這些內容放在一個(gè)單獨的文件中,即“wechat.yaml”,信息如下
cookie: ua_id=wuzWM9FKE14...user_agent: Mozilla/5.0...
你只需要稍后閱讀
# 讀取cookie和user_agentimport yamlwith 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中,我們可以看到每個(gè)文章的標題(title)、摘要(digest)、鏈接(link)、推送時(shí)間(update_time)和封面地址(cover)。
?
appmsgid 是每條推文的唯一標識符,aid 是每條推文的唯一標識符。
?
圖 6 ?
其實(shí)除了cookies,URL中的token參數也會(huì )用來(lái)限制爬蟲(chóng),所以上面代碼的輸出很可能是{'base_resp': {'ret': 200040,'err_msg ':'無(wú)效的 csrf 令牌'}}
?
接下來(lái),我們編寫(xiě)一個(gè)循環(huán)來(lái)獲取所有文章 JSON 并保存。
import jsonimport requestsimport timeimport randomimport yamlwith 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語(yǔ)句# 也方便重新運行時(shí)設置頁(yè)數i = 0while True: begin = i * 5 params["begin"] = str(begin) # 隨機暫停幾秒,避免過(guò)快的請求導致過(guò)快的被查到 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()) # 翻頁(yè) i += 1
在上面的代碼中,我還在“wechat.yaml”文件中存儲了fakeid和token。這是因為 fakeid 是每個(gè)公眾號的唯一標識符,令牌會(huì )經(jīng)常變化。這個(gè)信息可以通過(guò)解析URL獲取,也可以在開(kāi)發(fā)者工具中查看
圖7
爬取一段時(shí)間后,會(huì )遇到以下問(wèn)題
{'base_resp': {'err_msg': 'freq control', 'ret': 200013}}
此時(shí)在公眾號后臺嘗試插入超鏈接時(shí),會(huì )遇到如下提示
圖8
這是公眾號的流量限制,通常需要等待30-60分鐘才能繼續。為了完美處理這個(gè)問(wèn)題,你可能需要申請多個(gè)公眾號,可能需要對抗微信公眾號登錄系統,或者你可能需要設置代理池。
但是我不需要工業(yè)級的爬蟲(chóng),我只想爬取自己的公眾號信息,所以等了一個(gè)小時(shí),再次登錄公眾號,獲取cookie和token,運行。我不想用自己的興趣挑戰別人的工作。
最后,將結果保存為 JSON 格式。
# 保存結果為JSONjson_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))
或者提取文章identifier、標題、網(wǎng)址、發(fā)布時(shí)間四列,保存為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 csvwith open("app_msg_list.csv", "w") as file: file.writelines("\n".join(info_list))