Python 抓取微信公眾號賬號資訊

雨神姥爺發表於2016-10-23

搜狗微信搜尋提供兩種型別的關鍵詞搜尋,一種是搜尋公眾號文章內容,另一種是直接搜尋微信公眾號。通過微信公眾號搜尋可以獲取公眾號的基本資訊及最近釋出的10條文章,之前寫過一篇《Python 抓取微信公眾號文章》,今天來抓取一下微信公眾號的賬號資訊(→ 先看結果(2998條) ←)。

Python 抓取微信公眾號賬號資訊

爬蟲

首先通過首頁進入,可以按照類別抓取,通過“檢視更多”可以找出頁面連結規則:

Python 抓取微信公眾號賬號資訊

import requests as req
import re

reTypes = r'id="pc_\d*" uigs="(pc_\d*)">([\s\S]*?)</a>'
Entry = "http://weixin.sogou.com/"
entryPage = req.get(Entry)
allTypes = re.findall(reTypes, getUTF8(entryPage))

for (pcid, category) in allTypes:
    for page in range(1, 100):
        url = 'http://weixin.sogou.com/pcindex/pc/{}/{}.html'.format(pcid, page)
        print(url)

        categoryList = req.get(url)
        if categoryList.status_code != 200:
            break複製程式碼

上面程式碼通過載入更多頁面獲取載入列表,進而從其中抓取微信公眾號詳情頁面:

reProfile = r'<li id[\s\S]*?<a href="([\s\S]*?)"'
allProfiles = re.findall(reOAProfile, getUTF8(categoryList))
for profile in allProfiles:
    profilePage = req.get(profile)
    if profilePage.status_code != 200:
        continue複製程式碼

進入詳情頁面可以獲取公眾號的名稱/ID/功能介紹/賬號主體/頭像/二維碼/最近10篇文章等資訊:

Python 抓取微信公眾號賬號資訊

注意事項

詳情頁面連結:http://mp.weixin.qq.com/profile?src=3&timestamp=1477208282&ver=1&signature=8rYJ4QV2w5FXSOy6vGn37sUdcSLa8uoyHv3Ft7CrhZhB4wO-bbWG94aUCNexyB7lqRNSazua-2MROwkV835ilg==

1. 驗證碼

訪問詳情頁面時有可能需要驗證碼,自動識別驗證碼還是很有難度的,因此要做好爬蟲的偽裝工作。

2. 未儲存詳情頁面連結

詳情頁面的連結中有兩個重要引數:timestamp & signature,這說明頁面連結是有時效性的,所以儲存下來應該也沒用;

3. 二維碼

二維碼圖片連結同樣具有時效性,因此如需要最好將圖片下載下來。

用 Flask 展示結果

最近 Python 社群出現了一款非同步增強版的 Flask 框架:Sanic,基於uvloophttptools,可以達到非同步、更快的效果,但保持了與 Flask 一致的簡潔語法。雖然專案剛起步,還有很多基本功能為實現,但已經獲得了很多關注(2,222 Star)。這次本打算用抓取的微信公眾號資訊基於 Sanic 做一個簡單的互動應用,但無奈目前還沒有加入模板功能,非同步的 redis 驅動也還有 BUG 沒解決,所以簡單嘗試了一下之後還是切換回 Flask + SQLite,先把抓取結果呈現出來,後續有機會再做更新。

安裝 Sanic

Python 抓取微信公眾號賬號資訊

Debug Sanic

Python 抓取微信公眾號賬號資訊

Flask + SQLite App

from flask import g, Flask, render_template
import sqlite3

app = Flask(__name__)
DATABASE = "./db/wx.db"

def get_db():
    db = getattr(g, '_database', None)
    if db is None:
        db = g._database = sqlite3.connect(DATABASE)
    return db
@app.teardown_appcontext
def close_connection(exception):
    db = getattr(g, '_database', None)
    if db is not None:
        db.close()

@app.route("/<int:page>")
@app.route("/")
def hello(page=0):
    cur = get_db().cursor()
    cur.execute("SELECT * FROM wxoa LIMIT 30 OFFSET ?", (page*30, ))
    rows = []
    for row in cur.fetchall():
        rows.append(row)
    return render_template("app.html", wx=rows, cp=page)

if __name__ == "__main__":
    app.run(debug=True, port=8000)複製程式碼

檢視原文

相關文章