久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

歡度國慶??共享爬蟲之美??基于 Python 實(shí)現(xiàn)微信公眾號(hào)爬蟲(Python無所不能爬)

 zhulin1028 2021-12-29

此文章撰寫于國慶假期,以此紀(jì)念,。祝大家萬事大吉,心想事成,家和萬事興!國慶快樂!


微信公眾號(hào)爬蟲的基本原理

網(wǎng)上關(guān)于爬蟲的教程多如牛毛,但很少有看到微信公眾號(hào)爬蟲教程,要有也是基于搜狗微信的,不過搜狗提供的數(shù)據(jù)有諸多弊端,比如文章鏈接是臨時(shí)的,文章沒有閱讀量等指標(biāo),所以我想寫一個(gè)比較系統(tǒng)的關(guān)于如何通過手機(jī)客戶端利用 Python 爬微信公眾號(hào)文章的教程,并對(duì)公眾號(hào)文章做數(shù)據(jù)分析,為更好的運(yùn)營公眾號(hào)提供決策,。

爬蟲的基本原理

所謂爬蟲就是一個(gè)自動(dòng)化數(shù)據(jù)采集工具,你只要告訴它要采集哪些數(shù)據(jù),丟給它一個(gè) URL,就能自動(dòng)地抓取數(shù)據(jù)了。其背后的基本原理就是爬蟲程序向目標(biāo)服務(wù)器發(fā)起 HTTP 請(qǐng)求,然后目標(biāo)服務(wù)器返回響應(yīng)結(jié)果,爬蟲客戶端收到響應(yīng)并從中提取數(shù)據(jù),再進(jìn)行數(shù)據(jù)清洗,、數(shù)據(jù)存儲(chǔ)工作,。

爬蟲的基本流程

爬蟲流程也是一個(gè) HTTP 請(qǐng)求的過程,以瀏覽器訪問一個(gè)網(wǎng)址為例,從用戶輸入 URL 開始,客戶端通過 DNS 解析查詢到目標(biāo)服務(wù)器的 IP 地址,然后與之建立 TCP 連接,連接成功后,瀏覽器構(gòu)造一個(gè) HTTP 請(qǐng)求發(fā)送給服務(wù)器,服務(wù)器收到請(qǐng)求之后,從數(shù)據(jù)庫查到相應(yīng)的數(shù)據(jù)并封裝成一個(gè) HTTP 響應(yīng),然后將響應(yīng)結(jié)果返回給瀏覽器,瀏覽器對(duì)響應(yīng)內(nèi)容進(jìn)行數(shù)據(jù)解析、提取,、渲染并最終展示在你面前,。

HTTP 協(xié)議的請(qǐng)求和響應(yīng)都必須遵循固定的格式,只有遵循統(tǒng)一的 HTTP 請(qǐng)求格式,服務(wù)器才能正確解析不同客戶端發(fā)的請(qǐng)求,同樣地,服務(wù)器遵循統(tǒng)一的響應(yīng)格式,客戶端才得以正確解析不同網(wǎng)站發(fā)過來的響應(yīng)。

HTTP 請(qǐng)求格式

HTTP 請(qǐng)求由請(qǐng)求行,、請(qǐng)求頭,、空行、請(qǐng)求體組成,。

?請(qǐng)求行由三部分組成:

  1. 第一部分是請(qǐng)求方法,常見的請(qǐng)求方法有 GET,、POST、PUT,、DELETE,、HEAD
  2. 第二部分是客戶端要獲取的資源路徑
  3. 第三部分是客戶端使用的 HTTP 協(xié)議版本號(hào)

請(qǐng)求頭是客戶端向服務(wù)器發(fā)送請(qǐng)求的補(bǔ)充說明,比如 User-Agent 向服務(wù)器說明客戶端的身份。

請(qǐng)求體是客戶端向服務(wù)器提交的數(shù)據(jù),比如用戶登錄時(shí)需要提高的賬號(hào)密碼信息,。請(qǐng)求頭與請(qǐng)求體之間用空行隔開,。請(qǐng)求體并不是所有的請(qǐng)求都有的,比如一般的GET都不會(huì)帶有請(qǐng)求體,。

上圖就是瀏覽器登錄豆瓣時(shí)向服務(wù)器發(fā)送的HTTP POST 請(qǐng)求,請(qǐng)求體中指定了用戶名和密碼。

HTTP 響應(yīng)格式

HTTP 響應(yīng)格式與請(qǐng)求的格式很相似,也是由響應(yīng)行,、響應(yīng)頭,、空行、響應(yīng)體組成,。

響應(yīng)行也包含三部分,分別是服務(wù)端的 HTTP 版本號(hào),、響應(yīng)狀態(tài)碼、狀態(tài)說明,響應(yīng)狀態(tài)碼常見有 200,、400,、404、500,、502,、304 等等,一般以 2 開頭的表示服務(wù)器正常響應(yīng)了客戶端請(qǐng)求,4 開頭表示客戶端的請(qǐng)求有問題,5 開頭表示服務(wù)器出錯(cuò)了,沒法正確處理客戶端請(qǐng)求。狀態(tài)碼說明就是對(duì)該狀態(tài)碼的一個(gè)簡短描述,。

第二部分就是響應(yīng)頭,響應(yīng)頭與請(qǐng)求頭對(duì)應(yīng),是服務(wù)器對(duì)該響應(yīng)的一些附加說明,比如響應(yīng)內(nèi)容的格式是什么,響應(yīng)內(nèi)容的長度有多少,、什么時(shí)間返回給客戶端的、甚至還有一些 Cookie 信息也會(huì)放在響應(yīng)頭里面,。

第三部分是響應(yīng)體,它才是真正的響應(yīng)數(shù)據(jù),這些數(shù)據(jù)其實(shí)就是網(wǎng)頁的 HTML 源代碼,。

使用 Requests 實(shí)現(xiàn)一個(gè)簡單網(wǎng)頁爬蟲

Python 提供了非常多工具去實(shí)現(xiàn) HTTP 請(qǐng)求,但第三方開源庫提供的功能更豐富,你無需從 socket 通信開始寫,比如使用Pyton內(nèi)建模塊?urllib?請(qǐng)求一個(gè) URL 代碼示例如下:

import ssl from urllib.request;
import Request from urllib.request;
import urlopen context = ssl._create_unverified_context() 
# HTTP 請(qǐng)求 
request = Request(url="https:///pip.html", method="GET", headers={"Host": ""}, data=None) # HTTP 響應(yīng) 
response = urlopen(request, context=context) headers = response.info() # 響應(yīng)頭 
content = response.read() # 響應(yīng)體 
code = response.getcode() # 狀態(tài)碼

發(fā)起請(qǐng)求前首先要構(gòu)建請(qǐng)求對(duì)象 Request,指定 url 地址、請(qǐng)求方法,、請(qǐng)求頭,這里的請(qǐng)求體 data 為空,因?yàn)槟悴恍枰峤粩?shù)據(jù)給服務(wù)器,所以你也可以不指定,。urlopen 函數(shù)會(huì)自動(dòng)與目標(biāo)服務(wù)器建立連接,發(fā)送 HTTP 請(qǐng)求,該函數(shù)的返回值是一個(gè)響應(yīng)對(duì)象 Response,里面有響應(yīng)頭信息,響應(yīng)體,狀態(tài)碼之類的屬性。

但是,Python 提供的這個(gè)內(nèi)建模塊過于低級(jí),需要寫很多代碼,使用簡單爬蟲可以考慮 Requests,Requests 在GitHub 有近30k的Star,是一個(gè)很Pythonic的框架,。先來簡單熟悉一下這個(gè)框架的使用方式

安裝 requests

pip install requests

GET 請(qǐng)求

>>> r = requests.get("https:///ip") 
>>> r 
<Response [200]> # 響應(yīng)對(duì)象 
>>> r.status_code # 響應(yīng)狀態(tài)碼 200 
>>> r.content # 響應(yīng)內(nèi)容 
'{\n "origin": "183.237.232.123"\n}\n'

POST 請(qǐng)求

>>> r = requests.post('http:///post', data = {'key':'value'})

自定義請(qǐng)求頭

這個(gè)經(jīng)常會(huì)用到,服務(wù)器反爬蟲機(jī)制會(huì)判斷客戶端請(qǐng)求頭中的User-Agent是否來源于真實(shí)瀏覽器,所以,我們使用Requests經(jīng)常會(huì)指定UA偽裝成瀏覽器發(fā)起請(qǐng)求

>>> url = 'https:///headers' 
>>> headers = {'user-agent': 'Mozilla/5.0'}
>>> r = requests.get(url, headers=headers)

參數(shù)傳遞

很多時(shí)候URL后面會(huì)有一串很長的參數(shù),為了提高可讀性,requests 支持將參數(shù)抽離出來作為方法的參數(shù)(params)傳遞過去,而無需附在 URL 后面,例如請(qǐng)求 url http:///get?key=val ,可使用

>>> url = "http:///get" 
>>> r = requests.get(url, params={"key":"val"}) 
>>> r.url u'http:///get?key=val'

指定Cookie

Cookie 是web瀏覽器登錄網(wǎng)站的憑證,雖然 Cookie 也是請(qǐng)求頭的一部分,我們可以從中剝離出來,使用 Cookie 參數(shù)指定

>>> s = requests.get('http:///cookies', cookies={'from-my': 'browser'})
>>> s.text 
u'{\n "cookies": {\n "from-my": "browser"\n }\n}\n'

設(shè)置超時(shí)

當(dāng)發(fā)起一個(gè)請(qǐng)求遇到服務(wù)器響應(yīng)非常緩慢而你又不希望等待太久時(shí),可以指定 timeout 來設(shè)置請(qǐng)求超時(shí)時(shí)間,單位是秒,超過該時(shí)間還沒有連接服務(wù)器成功時(shí),請(qǐng)求將強(qiáng)行終止,。

r = requests.get('https://google.com', timeout=5)

設(shè)置代理

一段時(shí)間內(nèi)發(fā)送的請(qǐng)求太多容易被服務(wù)器判定為爬蟲,所以很多時(shí)候我們使用代理IP來偽裝客戶端的真實(shí)IP。

import requests 
proxies = { 'http': 'http://127.0.0.1:1080', 'https': 'http://127.0.0.1:1080', } 
r = requests.get('http://www./free/', proxies=proxies, timeout=2)

Session

如果想和服務(wù)器一直保持登錄(會(huì)話)狀態(tài),而不必每次都指定 cookies,那么可以使用 session,Session 提供的API和 requests 是一樣的,。

import requests 
s = requests.Session() 
s.cookies = requests.utils.cookiejar_from_dict({"a": "c"}) 
r = s.get('http:///cookies') 
print(r.text) 
# '{"cookies": {"a": "c"}}' 
r = s.get('http:///cookies') 
print(r.text) 
# '{"cookies": {"a": "c"}}'

小試牛刀

現(xiàn)在我們使用Requests完成一個(gè)爬取知乎專欄用戶關(guān)注列表的簡單爬蟲為例,找到任意一個(gè)專欄,打開它的關(guān)注列表,。用 Chrome 找到獲取粉絲列表的請(qǐng)求地址:https://www.zhihu.com/api/v4/columns/pythoneer/followers?include=data%5B%2A%5D.follower_count%2Cgender%2Cis_followed%2Cis_following&limit=10&offset=20。 我是怎么找到的?就是逐個(gè)點(diǎn)擊左側(cè)的請(qǐng)求,觀察右邊是否有數(shù)據(jù)出現(xiàn),那些以?.jpgjscss?結(jié)尾的靜態(tài)資源可直接忽略,。

現(xiàn)在我們用 Requests 模擬瀏覽器發(fā)送請(qǐng)求給服務(wù)器,寫程序前,我們要先分析出這個(gè)請(qǐng)求是怎么構(gòu)成的,請(qǐng)求URL是什么?請(qǐng)求頭有哪些?查詢參數(shù)有哪些?只有清楚了這些,你才好動(dòng)手寫代碼,掌握分析方法很重要,否則一頭霧水,。

回到前面那個(gè)URL,我們發(fā)現(xiàn)這個(gè)URL是獲取粉絲列表的接口,然后再來詳細(xì)分析一下這個(gè)請(qǐng)求是怎么構(gòu)成的。

  • 請(qǐng)求URL:https://www.zhihu.com/api/v4/columns/pythoneer/followers
  • 請(qǐng)求方法:GET
  • user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
  • 查詢參數(shù):
    • include: data[*].follower_count,gender,is_followed,is_following
    • offset: 0
    • limit: 10

利用這些請(qǐng)求數(shù)據(jù)我們就可以用requests這個(gè)庫來構(gòu)建一個(gè)請(qǐng)求,通過Python代碼來抓取這些數(shù)據(jù),。

import requests


class SimpleCrawler:

    def crawl(self, params=None):
        # 必須指定UA,否則知乎服務(wù)器會(huì)判定請(qǐng)求不合法

        url = "https://www.zhihu.com/api/v4/columns/pythoneer/followers"
        # 查詢參數(shù)
        params = {"limit": 20,
                  "offset": 0,
                  "include": "data[*].follower_count, gender, is_followed, is_following"}

        headers = {
            "authority": "www.zhihu.com",
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                          "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36",
        }
        response = requests.get(url, headers=headers, params=params)
        print("請(qǐng)求URL:", response.url)
        # 你可以先將返回的響應(yīng)數(shù)據(jù)打印出來,拷貝到 http://www./jsoneditor/ 分析其結(jié)構(gòu),。
        print("返回?cái)?shù)據(jù):", response.text)

        # 解析返回的數(shù)據(jù)
        for follower in response.json().get("data"):
            print(follower)


if __name__ == '__main__':
    SimpleCrawler().crawl()

這就是一個(gè)最簡單的基于 Requests 的單線程知乎專欄粉絲列表的爬蟲,requests 非常靈活,請(qǐng)求頭、請(qǐng)求參數(shù),、Cookie 信息都可以直接指定在請(qǐng)求方法中,返回值 response 如果是 json 格式可以直接調(diào)用json()方法返回 python 對(duì)象。關(guān)于 Requests 的更多使用方法可以參考官方文檔:Requests: HTTP for Humans? — Requests 2.26.0 documentation

使用 Fiddler 抓包分析公眾號(hào)請(qǐng)求過程

上一節(jié)我們熟悉了 Requests 基本使用方法,配合 Chrome 瀏覽器實(shí)現(xiàn)了一個(gè)簡單爬蟲,但因?yàn)槲⑿殴娞?hào)的封閉性,微信公眾平臺(tái)并沒有對(duì)外提供 Web 端入口,只能通過手機(jī)客戶端接收,、查看公眾號(hào)文章,所以,為了窺探到公眾號(hào)背后的網(wǎng)絡(luò)請(qǐng)求,我們需要借以代理工具的輔助,。

HTTP代理工具又稱為抓包工具,主流的抓包工具 Windows 平臺(tái)有 Fiddler,macOS 有 Charles,阿里開源了一款工具叫 AnyProxy,。它們的基本原理都是類似的,就是通過在手機(jī)客戶端設(shè)置好代理IP和端口,客戶端所有的 HTTP、HTTPS 請(qǐng)求就會(huì)經(jīng)過代理工具,在代理工具中就可以清晰地看到每個(gè)請(qǐng)求的細(xì)節(jié),然后可以分析出每個(gè)請(qǐng)求是如何構(gòu)造的,弄清楚這些之后,我們就可以用 Python 模擬發(fā)起請(qǐng)求,進(jìn)而得到我們想要的數(shù)據(jù),。

Fiddler 下載地址是?Download Fiddler Web Debugging Tool for Free by Telerik,安裝包就 4M 多,在配置之前,首先要確保你的手機(jī)和電腦在同一個(gè)局域網(wǎng),如果不在同一個(gè)局域網(wǎng),你可以買個(gè)隨身WiFi,在你電腦上搭建一個(gè)極簡無線路由器,。安裝過程一路點(diǎn)擊下一步完成就可以了。

Fiddler 配置

選擇?Tools > Fiddler Options > Connections

Fiddler 默認(rèn)的端口是使用 8888,如果該端口已經(jīng)被其它程序占用了,你需要手動(dòng)更改,勾選 Allow remote computers to connect,其它的選擇默認(rèn)配置就好,配置更新后記得重啟 Fiddler,。一定要重啟 Fiddler,否則代理無效,。

接下來你需要配置手機(jī),我們以 Android 設(shè)備為例,現(xiàn)在假設(shè)你的手機(jī)和電腦已經(jīng)在同一個(gè)局域網(wǎng)(只要連的是同一個(gè)路由器就在同局域網(wǎng)內(nèi)),找到電腦的 IP 地址,在 Fiddler 右上角有個(gè) Online 圖標(biāo),鼠標(biāo)移過去就能看到IP了,你也可以在CMD窗口使用?ipconfig?命令查看到

Android 手機(jī)代理配置

進(jìn)入手機(jī)的 WLAN 設(shè)置,選擇當(dāng)前所在局域網(wǎng)的 WiFi 鏈接,設(shè)置代理服務(wù)器的 IP 和端口,我這是以小米設(shè)備為例,其它 Android 手機(jī)的配置過程大同小異。

測試代理有沒有設(shè)置成功可以在手機(jī)瀏覽器訪問你配置的地址:http://192.168.31.236:8888/ 會(huì)顯示 Fiddler 的回顯頁面,說明配置成功,。

現(xiàn)在你打開任意一個(gè)HTTP協(xié)議的網(wǎng)站都能看到請(qǐng)求會(huì)出現(xiàn)在 Fiddler 窗口,但是 HTTPS 的請(qǐng)求并沒有出現(xiàn)在 Fiddler 中,其實(shí)還差一個(gè)步驟,需要在 Fiddler 中激活 HTTPS 抓取設(shè)置,。在 Fiddler 選擇?Tools > Fiddler Options > HTTPS > Decrypt HTTPS traffic, 重啟 Fiddler。

為了能夠讓 Fiddler 截取 HTTPS 請(qǐng)求,客戶端都需要安裝且信任 Fiddler 生成的 CA 證書,否則會(huì)出現(xiàn)“網(wǎng)絡(luò)出錯(cuò),輕觸屏幕重新加載:-1200”的錯(cuò)誤,。在瀏覽器打開 Fiddler 回顯頁面 http://192.168.31.236:8888/ 下載?FiddlerRoot certificate,下載并安裝證書,并驗(yàn)證通過,。

iOS下載安裝完成之后還要從?設(shè)置->通用->關(guān)于本機(jī)->證書信任設(shè)置?中把 Fiddler 證書的開關(guān)打開

Android 手機(jī)下載保存證書后從系統(tǒng)設(shè)置里面找到系統(tǒng)安全,從SD卡安裝證書,如果沒有安裝證書,打開微信公眾號(hào)的時(shí)候會(huì)彈出警告。

至此,所有的配置都完成了,現(xiàn)在打開微信隨便選擇一個(gè)公眾號(hào),查看公眾號(hào)的所有歷史文章列表,。微信在2018年6月份對(duì) iOS 版本的微信以及部分 Android 版微信針對(duì)公眾號(hào)進(jìn)行了大幅調(diào)整,改為現(xiàn)在的信息流方式,現(xiàn)在要獲取某個(gè)公眾號(hào)下面「所有文章列表」大概需要經(jīng)過以下四個(gè)步驟:

如果你的微信版本還不是信息流方式展示的,那么應(yīng)該是Android版本(微信采用的ABTest,不同的用戶呈現(xiàn)的方式不一樣)

同時(shí)觀察 Fiddler 主面板

進(jìn)入「全部消息」頁面時(shí),在 Fiddler 上已經(jīng)能看到有請(qǐng)求進(jìn)來了,說明公眾號(hào)的文章走的都是HTTP協(xié)議,這些請(qǐng)求就是微信客戶端向微信服務(wù)器發(fā)送的HTTP請(qǐng)求,。

注意:第一次請(qǐng)求「全部消息」的時(shí)候你看到的可能是一片空白:

在Fiddler或Charles中看到的請(qǐng)求數(shù)據(jù)是這樣的:

這個(gè)時(shí)候你要直接從左上角叉掉重新進(jìn)入「全部消息」頁面。

現(xiàn)在簡單介紹一下這個(gè)請(qǐng)求面板上的每個(gè)模塊的意義,。

這樣說明這個(gè)請(qǐng)求被微信服務(wù)器判定為一次非法的請(qǐng)求,這時(shí)你可以叉掉該頁面重新進(jìn)入「全部消息」頁面,。不出意外的話就能正常看到全部文章列表了,同時(shí)也能在Fiddler中看到正常的數(shù)據(jù)請(qǐng)求了,。

我把上面的主面板劃分為 7 大塊,你需要理解每塊的內(nèi)容,后面才有可能會(huì)用 Python 代碼來模擬微信請(qǐng)求,。

1、服務(wù)器的響應(yīng)結(jié)果,200 表示服務(wù)器對(duì)該請(qǐng)求響應(yīng)成功
2,、請(qǐng)求協(xié)議,微信的請(qǐng)求協(xié)議都是基 于HTTPS 的,所以前面一定要配置好,不然你看不到 HTTPS 的請(qǐng)求,。
3、微信服務(wù)器主機(jī)名
4,、請(qǐng)求路徑
5,、請(qǐng)求行,包括了請(qǐng)求方法(GET),請(qǐng)求協(xié)議(HTTP/1.1),請(qǐng)求路徑(/mp/profile_ext...后面還有很長一串參數(shù)) 6、包括Cookie信息在內(nèi)的請(qǐng)求頭,。
7,、微信服務(wù)器返回的響應(yīng)數(shù)據(jù),我們分別切換成 TextView 和 WebView 看一下返回的數(shù)據(jù)是什么樣的。

TextView 模式下的預(yù)覽效果是服務(wù)器返回的 HTML 源代碼

WebView 模式是 HTML 代碼經(jīng)過渲染之后的效果,其實(shí)就是我們在手機(jī)微信中看到的效果,只不過因?yàn)槿狈邮?#xff0c;所以沒有手機(jī)上看到的美化效果,。

如果服務(wù)器返回的是 Json格式或者是 XML,你還可以切換到對(duì)應(yīng)的頁面預(yù)覽查看,。

小結(jié)

配置好Fiddler的幾個(gè)步驟主要包括指定監(jiān)控的端口,開通HTTPS流量解密功能,同時(shí),客戶端需要安裝CA證書。下一節(jié)我們基于Requests模擬像微信服務(wù)器發(fā)起請(qǐng)求,。

抓取第一篇微信公眾號(hào)文章

打開微信歷史消息頁面,我們從 Fiddler 看到了很多請(qǐng)求,為了找到微信歷史文章的接口,我們要逐個(gè)查看 Response 返回的內(nèi)容,最后發(fā)現(xiàn)第 11 個(gè)請(qǐng)求 "https://mp.weixin.qq.com/mp/profile_ext?action=home..." 就是我們要尋找的(我是怎么找到的呢?這個(gè)和你的經(jīng)驗(yàn)有關(guān),你可以點(diǎn)擊逐個(gè)請(qǐng)求,看看返回的Response內(nèi)容是不是期望的內(nèi)容)

確定微信公眾號(hào)的請(qǐng)求HOST是 mp.weixin.qq.com 之后,我們可以使用過濾器來過濾掉不相關(guān)的請(qǐng)求,。

爬蟲的基本原理就是模擬瀏覽器發(fā)送 HTTP 請(qǐng)求,然后從服務(wù)器得到響應(yīng)結(jié)果,現(xiàn)在我們就用 Python 實(shí)現(xiàn)如何發(fā)送一個(gè) HTTP 請(qǐng)求。這里我們使用 requests 庫來發(fā)送請(qǐng)求,。

創(chuàng)建一個(gè) Pycharm 項(xiàng)目

我們使用 Pycharm 作為開發(fā)工具,你也可以使用其它你熟悉的工具,Python 環(huán)境是 Python3(推薦使用 Python3.6),先創(chuàng)建一個(gè)項(xiàng)目 weixincrawler

現(xiàn)在我們來編寫一個(gè)最粗糙的版本,你需要做兩件事:

  • 1:找到完整URL請(qǐng)求地址
  • 2:找到完整的請(qǐng)求頭(headers)信息,Headers里面包括了cookie,、User-agent,、Host 等信息。

我們直接從 Fiddler 請(qǐng)求中拷貝 URL 和 Headers, 右鍵 -> Copy -> Just Url/Headers Only

最終拷貝出來的URL很長,它包含了很多的參數(shù):

url = "https://mp.weixin.qq.com/mp/profile_ext"       "?action=home"       "&__biz=MjM5MzgyODQxMQ=="       "&scene=124"       "&devicetype=android-24"       "&version=26051633&lang=zh_CN"       "&nettype=WIFI&a8scene=3"       "&pass_ticket=MXADI5SFjXvX7DFPRuUEJhWHEWvRha2x1Re%2BoJkveUxIonMfnxY1kM9cOPmm6JRx"       "&wx_header=1"

暫且不去分析(猜測)每個(gè)參數(shù)的意義,也不知道那些參數(shù)是必須的,總之我把這些參數(shù)全部提取出來,。然后把 Headers 拷貝出來,發(fā)現(xiàn) Fiddler 把 請(qǐng)求行,、響應(yīng)行、響應(yīng)頭都包括進(jìn)來了,我們只需要中間的請(qǐng)求頭部分,。

因?yàn)?requests.get 方法里面的 headers 參數(shù)必須是字典對(duì)象,所以,先要寫個(gè)函數(shù)把剛剛拷貝的字符串轉(zhuǎn)換成字典對(duì)象,。

def headers_to_dict(headers):
    """
    將字符串
    '''
    Host: mp.weixin.qq.com
    Connection: keep-alive
    Cache-Control: max-age=
    '''
    轉(zhuǎn)換成字典對(duì)象
    {
        "Host": "mp.weixin.qq.com",
        "Connection": "keep-alive",
        "Cache-Control":"max-age="
    }
    :param headers: str
    :return: dict
    """
    headers = headers.split("\n")
    d_headers = dict()
    for h in headers:
        if h:
            k, v = h.split(":", 1)
            d_headers[k] = v.strip()
    return d_headers

最終 v0.1 版本出來了,不出意外的話,公眾號(hào)歷史文章數(shù)據(jù)就在 response.text 中。如果返回的內(nèi)容非常短,而且title標(biāo)簽是<title>驗(yàn)證</title>,那么說明你的請(qǐng)求參數(shù)或者請(qǐng)求頭有誤,最有可能的一種請(qǐng)求就是 Headers 里面的 Cookie 字段過期,從手機(jī)微信端重新發(fā)起一次請(qǐng)求獲取最新的請(qǐng)求參數(shù)和請(qǐng)求頭試試,。

# v0.1
def crawl():
    url = "https://mp.weixin.qq.com/..." # 省略了
    headers = """  # 省略了
Host: mp.weixin.qq.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
    """
    headers = headers_to_dict(headers)
    response = requests.get(url, headers=headers, verify=False)
    print(response.text)
最后,我們順帶把響應(yīng)結(jié)果另存為html文件,以便后面重復(fù)使用,分析里面的內(nèi)容
with open("weixin_history.html", "w", encoding="utf-8") as f:
    f.write(response.text)

用瀏覽器打開 weixin_history.html 文件,查看該頁面的源代碼,搜索微信歷史文章標(biāo)題的關(guān)鍵字 "11月贈(zèng)書"(就是我以往發(fā)的文章),你會(huì)發(fā)現(xiàn),歷史文章封裝在叫 msgList 的數(shù)組中(實(shí)際上該數(shù)組包裝在字典結(jié)構(gòu)中),這是一個(gè) Json 格式的數(shù)據(jù),但是里面還有 html 轉(zhuǎn)義字符需要處理

接下來我們就來寫一個(gè)方法提取出歷史文章數(shù)據(jù),分三個(gè)步驟,首先用正則提取數(shù)據(jù)內(nèi)容,然后 html 轉(zhuǎn)義處理,最終得到一個(gè)列表對(duì)象,返回最近發(fā)布的10篇文章,。

def extract_data(html_content):
    """
    從html頁面中提取歷史文章數(shù)據(jù)
    :param html_content 頁面源代碼
    :return: 歷史文章列表
    """
    import re
    import html
    import json

    rex = "msgList = '({.*?})'"
    pattern = re.compile(pattern=rex, flags=re.S)
    match = pattern.search(html_content)
    if match:
        data = match.group(1)
        data = html.unescape(data)
        data = json.loads(data)
        articles = data.get("list")
        for item in articles:
            print(item)
        return articles

最終提取出來的數(shù)據(jù)總共有10條,就是最近發(fā)表的10條數(shù)據(jù),我們看看每條數(shù)據(jù)返回有哪些字段。

article = {'app_msg_ext_info': 
                {'title': '11月贈(zèng)書,總共10本,附Python書單',
                 'copyright_stat': 11,
                 'is_multi': 1,
                 'content': '',
                 'author': '劉志軍',
                 'subtype': 9,
                 'del_flag': 1,
                 'fileid': 502883895,
                 'content_url': 'http:\\/\\/mp.weixin.qq.com...',
                 ''
                 'digest': '十一月份贈(zèng)書福利如期而至,更多驚喜等著你',
                 'cover': 'http:\\/\\/mmbiz.qpic.cn\\...',
                 'multi_app_msg_item_list': [{'fileid': 861719336,
                                              'content_url': 'http:\\/\\/mp.weixin.qq.com',
                                              'content': '', 'copyright_stat': 11,
                                              'cover': 'http:\\/\\/mmbiz.qpic.cn',
                                              'del_flag': 1,
                                              'digest': '多數(shù)情況下,人是種短視的動(dòng)物',
                                              'source_url': '',
                                              'title': '羅胖60秒:諾貝爾獎(jiǎng)設(shè)立時(shí),為何會(huì)被罵?',
                                              'author': '羅振宇'
                                              }],
                 'source_url': 'https:\\/\\/github.com\'
                 },
      'comm_msg_info': {'datetime': 1511827200,
                        'status': 2,
                        'id': 1000000161,
                        'fakeid': '2393828411',
                        'content': '',
                        'type': 49}}

comm_msg_info.datetimeapp_msg_ext_info中的字段信息就是第一篇文章的字段信息,分別對(duì)應(yīng):

  • title:文章標(biāo)題
  • content_url:文章鏈接
  • source_url:原文鏈接,有可能為空
  • digest:摘要
  • cover:封面圖
  • datetime:推送時(shí)間

后面幾篇文章以列表的形式保存在 multi_app_msg_item_list 字段中,。

到此,公眾號(hào)文章的基本信息就抓到了,但也僅僅只是公眾號(hào)的前10條推送,。

資源來源于網(wǎng)絡(luò),純屬分享,不做商業(yè)用途,如若侵犯了您的權(quán)益和利益,請(qǐng)告知?jiǎng)h除。

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多