Python 抓取微信公衆號帳號信息

搜狗微信搜索提供兩種類型的關鍵詞搜索,一種是搜索公衆號文章內容,另外一種是直接搜索微信公衆號。經過微信公衆號搜索能夠獲取公衆號的基本信息及最近發佈的10條文章,以前寫過一篇《Python 抓取微信公衆號文章》,今天來抓取一下微信公衆號的帳號信息(→ 先看結果(2998條) ←)。html

爬蟲

首先經過首頁進入,能夠按照類別抓取,經過「查看更多」能夠找出頁面連接規則:git

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複製代碼

上面代碼經過加載更多頁面獲取加載列表,進而從其中抓取微信公衆號詳情頁面:github

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篇文章等信息:redis

注意事項

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

1. 驗證碼

訪問詳情頁面時有可能須要驗證碼,自動識別驗證碼仍是頗有難度的,所以要作好爬蟲的假裝工做。flask

2. 未保存詳情頁面連接

詳情頁面的連接中有兩個重要參數:timestamp & signature,這說明頁面連接是有時效性的,因此保存下來應該也沒用;微信

3. 二維碼

二維碼圖片連接一樣具備時效性,所以如須要最好將圖片下載下來。app

用 Flask 展現結果

最近 Python 社區出現了一款異步加強版的 Flask 框架:Sanic,基於uvloophttptools,能夠達到異步、更快的效果,但保持了與 Flask 一致的簡潔語法。雖然項目剛起步,還有不少基本功能爲實現,但已經得到了不少關注(2,222 Star)。此次本打算用抓取的微信公衆號信息基於 Sanic 作一個簡單的交互應用,但無奈目前尚未加入模板功能,異步的 redis 驅動也還有 BUG 沒解決,因此簡單嘗試了一下以後仍是切換回 Flask + SQLite,先把抓取結果呈現出來,後續有機會再作更新。框架

安裝 Sanic

Debug Sanic

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)複製代碼

查看原文異步

相關文章
相關標籤/搜索