
爬蟲
經(jīng)常有朋友需要幫忙做公眾號(hào)文章爬取,這次來做一個(gè)各種方法的匯總說明。
目前爬取微信公眾號(hào)的方法主要有3種:
- 通過爬取第三方的公眾號(hào)文章聚合網(wǎng)站
- 通過微信公眾平臺(tái)引用文章接口
- 通過抓包程序,分析微信app訪問公眾號(hào)文章的接口
通過第三方的公眾號(hào)文章聚合網(wǎng)站爬取
微信公眾號(hào)文章一直沒有提供一個(gè)對(duì)外的搜索功能,直到2013年微信投資搜狗之后,搜狗搜索接入微信公眾號(hào)數(shù)據(jù),從此使用搜狗搜索就可以瀏覽或查詢到相關(guān)公眾號(hào)以及文章。
域名是: https://weixin.sogou.com/

搜狗微信
可以直接搜索公眾號(hào)或者文章的關(guān)鍵字,一些熱門的公眾號(hào)更新還是很及時(shí)的,幾乎做到了和微信同步。

公眾號(hào)搜索
所以,爬一些熱門公眾號(hào)可以使用搜狗微信的接口來做,但是一些小眾公眾號(hào)是搜索不到的,而且搜狗的防爬機(jī)制更新的比較勤,獲取數(shù)據(jù)的接口變化的比較快,經(jīng)常兩三個(gè)月就有調(diào)整,導(dǎo)致爬蟲很容易掛,這里還是建議使用
selenium 爬比較省心。另外搜狗對(duì)每個(gè)ip也有訪問限制,訪問太頻ip會(huì)被封禁24小時(shí),需要買個(gè)ip池來做應(yīng)對(duì)。還有一些其他公眾號(hào)文章聚合網(wǎng)站(比如傳送門)也都存在更新不及時(shí)或者沒有收錄的問題,畢竟搜狗這個(gè)親兒子都不行。
通過微信公眾平臺(tái)引用文章接口
這個(gè)接口比較隱蔽而且沒法匿名訪問,所有得有一個(gè)公眾號(hào),建議新注冊(cè)一個(gè)公眾號(hào)比較好,免得被封。
下面開始具體步驟:首先登錄自己的微信公眾號(hào),在進(jìn)去的首頁選擇新建群發(fā),然后再點(diǎn)擊自建圖文,在文章編輯工具欄中找到超鏈接,如下圖:

點(diǎn)擊超鏈接
點(diǎn)擊這個(gè)超鏈接按鈕,就會(huì)彈出一個(gè)對(duì)話框,鏈接輸入方式這一項(xiàng)選中
查找文章,如下圖:
查找文章
到這里就可以輸入公眾號(hào)的名字,回車之后微信就會(huì)返回相匹配的公眾號(hào)列表,如下圖:

搜索公眾號(hào)
接著點(diǎn)擊你想抓取的公眾號(hào),就會(huì)顯示具體的文章列表了,已經(jīng)是按時(shí)間倒序了,最新的文章就是第一條了。如下圖:

文章列表
微信的分頁機(jī)制比較奇怪,每個(gè)公眾號(hào)的每頁顯示的數(shù)據(jù)條數(shù)是不一樣的,分頁爬的時(shí)候要處理一下。
通過chrome分析網(wǎng)絡(luò)請(qǐng)求的數(shù)據(jù),我們想要的數(shù)據(jù)已經(jīng)基本拿到了,文章鏈接、封面、發(fā)布日期、副標(biāo)題等,如下圖:

網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)
OK,這種方法爬取的原理講完了,下面開始實(shí)操了??。
由于微信公眾平臺(tái)登錄驗(yàn)證比較嚴(yán)格,輸入密碼之后還必須要手機(jī)掃碼確認(rèn)才能登錄進(jìn)去,所以最好還是使用
selenium做自動(dòng)化比較好。具體微信接口的分析過程我就不列了,直接貼代碼了:
import re
import time
import random
import traceback
import requests
from selenium import webdriver
class Spider(object):
'''
微信公眾號(hào)文章爬蟲
'''
def __init__(self):
# 微信公眾號(hào)賬號(hào)
self.account = ''
# 微信公眾號(hào)密碼
self.pwd = ''
def create_driver(self):
'''
初始化 webdriver
'''
options = webdriver.ChromeOptions()
# 禁用gpu加速,防止出一些未知bug
options.add_argument('--disable-gpu')
# 這里我用 chromedriver 作為 webdriver
# 可以去 http://chromedriver.chromium.org/downloads 下載你的chrome對(duì)應(yīng)版本
self.driver = webdriver.Chrome(executable_path='./chromedriver', chrome_options=options)
# 設(shè)置一個(gè)隱性等待 5s
self.driver.implicitly_wait(5)
def log(self, msg):
'''
格式化打印
'''
print('------ %s ------' % msg)
def login(self):
'''
登錄拿 cookies
'''
try:
self.create_driver()
# 訪問微信公眾平臺(tái)
self.driver.get('https://mp.weixin.qq.com/')
# 等待網(wǎng)頁加載完畢
time.sleep(3)
# 輸入賬號(hào)
self.driver.find_element_by_xpath("./*//input[@name='account']").clear()
self.driver.find_element_by_xpath("./*//input[@name='account']").send_keys(self.account)
# 輸入密碼
self.driver.find_element_by_xpath("./*//input[@name='password']").clear()
self.driver.find_element_by_xpath("./*//input[@name='password']").send_keys(self.pwd)
# 點(diǎn)擊登錄
self.driver.find_elements_by_class_name('btn_login')[0].click()
self.log("請(qǐng)拿手機(jī)掃碼二維碼登錄公眾號(hào)")
# 等待手機(jī)掃描
time.sleep(10)
self.log("登錄成功")
# 獲取cookies 然后保存到變量上,后面要用
self.cookies = dict([[x['name'], x['value']] for x in self.driver.get_cookies()])
except Exception as e:
traceback.print_exc()
finally:
# 退出 chorme
self.driver.quit()
def get_article(self, query=''):
try:
url = 'https://mp.weixin.qq.com'
# 設(shè)置headers
headers = {
"HOST": "mp.weixin.qq.com",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36"
}
# 登錄之后的微信公眾號(hào)首頁url變化為:https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token=1849751598,
# 從這里獲取token信息
response = requests.get(url=url, cookies=self.cookies)
token = re.findall(r'token=(\d+)', str(response.url))[0]
time.sleep(2)
self.log('正在查詢[ %s ]相關(guān)公眾號(hào)' % query)
search_url = 'https://mp.weixin.qq.com/cgi-bin/searchbiz?'
# 搜索微信公眾號(hào)接口需要傳入的參數(shù),
# 有三個(gè)變量:微信公眾號(hào)token、隨機(jī)數(shù)random、搜索的微信公眾號(hào)名字
params = {
'action': 'search_biz',
'token': token,
'random': random.random(),
'query': query,
'lang': 'zh_CN',
'f': 'json',
'ajax': '1',
'begin': '0',
'count': '5'
}
# 打開搜索微信公眾號(hào)接口地址,需要傳入相關(guān)參數(shù)信息如:cookies、params、headers
response = requests.get(search_url, cookies=self.cookies, headers=headers, params=params)
time.sleep(2)
# 取搜索結(jié)果中的第一個(gè)公眾號(hào)
lists = response.json().get('list')[0]
# 獲取這個(gè)公眾號(hào)的fakeid,后面爬取公眾號(hào)文章需要此字段
fakeid = lists.get('fakeid')
nickname = lists.get('nickname')
# 微信公眾號(hào)文章接口地址
search_url = 'https://mp.weixin.qq.com/cgi-bin/appmsg?'
# 搜索文章需要傳入幾個(gè)參數(shù):登錄的公眾號(hào)token、要爬取文章的公眾號(hào)fakeid、隨機(jī)數(shù)random
params = {
'action': 'list_ex',
'token': token,
'random': random.random(),
'fakeid': fakeid,
'lang': 'zh_CN',
'f': 'json',
'ajax': '1',
'begin': '0', # 不同頁,此參數(shù)變化,變化規(guī)則為每頁加5
'count': '5',
'query': '',
'type': '9'
}
self.log('正在查詢公眾號(hào)[ %s ]相關(guān)文章' % nickname)
# 打開搜索的微信公眾號(hào)文章列表頁
response = requests.get(search_url, cookies=self.cookies, headers=headers, params=params)
time.sleep(2)
for per in response.json().get('app_msg_list', []):
print('title ---> %s' % per.get('title'))
print('link ---> %s' % per.get('link'))
# print('cover ---> %s' % per.get('cover'))
except Exception as e:
traceback.print_exc()
if __name__ == '__main__':
spider = Spider()
spider.login()
spider.get_article('python')
代碼只是作為學(xué)習(xí)使用,沒有做分頁查詢之類。
據(jù)網(wǎng)友稱,這個(gè)接口也有訪問頻次限制,一天幾百次還是沒啥問題,太快或者太多次訪問就會(huì)被封24小時(shí)。
下一篇我們來講講如何獲取文章的閱讀數(shù)和點(diǎn)贊數(shù)。
參考文章
https://segmentfault.com/a/1190000015642808
https://cuiqingcai.com/4652.html