HOME 首頁
SERVICE 服務(wù)產(chǎn)品
XINMEITI 新媒體代運營
CASE 服務(wù)案例
NEWS 熱點資訊
ABOUT 關(guān)于我們
CONTACT 聯(lián)系我們
創(chuàng)意嶺
讓品牌有溫度、有情感
專注品牌策劃15年

    抓取微信APP登錄數(shù)據(jù)

    發(fā)布時間:2023-03-21 12:44:52     稿源: 創(chuàng)意嶺    閱讀: 1118        問大家

    大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關(guān)于抓取微信APP登錄數(shù)據(jù)的問題,以下是小編對此問題的歸納整理,讓我們一起來看看吧。

    本文目錄:

    抓取微信APP登錄數(shù)據(jù)

    一、如何抓取微信所有公眾號最新文章

    經(jīng)常有朋友需要幫忙做公眾號文章爬取,這次來做一個各種方法的匯總說明。

    目前爬取微信公眾號的方法主要有3種:

    • 通過爬取第三方的公眾號文章聚合網(wǎng)站

    • 通過微信公眾平臺引用文章接口

    • 通過抓包程序,分析微信app訪問公眾號文章的接口

    • 通過第三方的公眾號文章聚合網(wǎng)站爬取

      微信公眾號文章一直沒有提供一個對外的搜索功能,直到2013年微信投資搜狗之后,搜狗搜索接入微信公眾號數(shù)據(jù),從此使用搜狗搜索就可以瀏覽或查詢到相關(guān)公眾號以及文章。

      域名是: https://weixin.sogou.com/

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

    所以,爬一些熱門公眾號可以使用搜狗微信的接口來做,但是一些小眾公眾號是搜索不到的,而且搜狗的防爬機制更新的比較勤,獲取數(shù)據(jù)的接口變化的比較快,經(jīng)常兩三個月就有調(diào)整,導致爬蟲很容易掛,這里還是建議使用 selenium爬比較省心。另外搜狗對每個ip也有訪問限制,訪問太頻ip會被封禁24小時,需要買個ip池來做應對。

    還有一些其他公眾號文章聚合網(wǎng)站(比如傳送門)也都存在更新不及時或者沒有收錄的問題,畢竟搜狗這個親兒子都不行。

    通過微信公眾平臺引用文章接口

    這個接口比較隱蔽而且沒法匿名訪問,所有得有一個公眾號,建議新注冊一個公眾號比較好,免得被封。

    下面開始具體步驟:首先登錄自己的微信公眾號,在進去的首頁選擇 新建群發(fā),然后再點擊 自建圖文,在文章編輯工具欄中找到 超鏈接,如下圖:

    點擊這個超鏈接按鈕,就會彈出一個對話框,鏈接輸入方式這一項選中 查找文章,如下圖:

    到這里就可以輸入公眾號的名字,回車之后微信就會返回相匹配的公眾號列表,接著點擊你想抓取的公眾號,就會顯示具體的文章列表了,已經(jīng)是按時間倒序了,最新的文章就是第一條了。

    微信的分頁機制比較奇怪,每個公眾號的每頁顯示的數(shù)據(jù)條數(shù)是不一樣的,分頁爬的時候要處理一下。

    通過chrome分析網(wǎng)絡(luò)請求的數(shù)據(jù),我們想要的數(shù)據(jù)已經(jīng)基本拿到了,文章鏈接、封面、發(fā)布日期、副標題等,如

    由于微信公眾平臺登錄驗證比較嚴格,輸入密碼之后還必須要手機掃碼確認才能登錄進去,所以最好還是使用 selenium做自動化比較好。具體微信接口的分析過程我就不列了,直接貼代碼了:

    • import re

    • import time

    • import random

    • import traceback

    • import requests

    • from selenium import webdriver

    • class Spider(object):

    • '''

    • 微信公眾號文章爬蟲

    • '''

    • def __init__(self):

    • # 微信公眾號賬號

    • self.account = '286394973@qq.com'

    • # 微信公眾號密碼

    • self.pwd = 'lei4649861'

    • def create_driver(self):

    • '''

    • 初始化 webdriver

    • '''

    • options = webdriver.ChromeOptions()

    • # 禁用gpu加速,防止出一些未知bug

    • options.add_argument('--disable-gpu')

    • # 這里我用 chromedriver 作為 webdriver

    • # 可以去 http://chromedriver.chromium.org/downloads 下載你的chrome對應版本

    • self.driver = webdriver.Chrome(executable_path='./chromedriver', chrome_options=options)

    • # 設(shè)置一個隱性等待 5s

    • self.driver.implicitly_wait(5)

    • def log(self, msg):

    • '''

    • 格式化打印

    • '''

    • print('------ %s ------' % msg)

    • def login(self):

    • '''

    • 登錄拿 cookies

    • '''

    • try:

    • self.create_driver()

    • # 訪問微信公眾平臺

    • self.driver.get('https://mp.weixin.qq.com/')

    • # 等待網(wǎng)頁加載完畢

    • time.sleep(3)

    • # 輸入賬號

    • 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)

    • # 點擊登錄

    • self.driver.find_elements_by_class_name('btn_login')[0].click()

    • self.log("請拿手機掃碼二維碼登錄公眾號")

    • # 等待手機掃描

    • 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"

    • }

    • # 登錄之后的微信公眾號首頁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)公眾號' % query)

    • search_url = 'https://mp.weixin.qq.com/cgi-bin/searchbiz?'

    • # 搜索微信公眾號接口需要傳入的參數(shù),

    • # 有三個變量:微信公眾號token、隨機數(shù)random、搜索的微信公眾號名字

    • params = {

    • 'action': 'search_biz',

    • 'token': token,

    • 'random': random.random(),

    • 'query': query,

    • 'lang': 'zh_CN',

    • 'f': 'json',

    • 'ajax': '1',

    • 'begin': '0',

    • 'count': '5'

    • }

    • # 打開搜索微信公眾號接口地址,需要傳入相關(guān)參數(shù)信息如:cookies、params、headers

    • response = requests.get(search_url, cookies=self.cookies, headers=headers, params=params)

    • time.sleep(2)

    • # 取搜索結(jié)果中的第一個公眾號

    • lists = response.json().get('list')[0]

    • # 獲取這個公眾號的fakeid,后面爬取公眾號文章需要此字段

    • fakeid = lists.get('fakeid')

    • nickname = lists.get('nickname')

    • # 微信公眾號文章接口地址

    • search_url = 'https://mp.weixin.qq.com/cgi-bin/appmsg?'

    • # 搜索文章需要傳入幾個參數(shù):登錄的公眾號token、要爬取文章的公眾號fakeid、隨機數(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('正在查詢公眾號[ %s ]相關(guān)文章' % nickname)

    • # 打開搜索的微信公眾號文章列表頁

    • 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')

    代碼只是作為學習使用,沒有做分頁查詢之類。實測過接口存在訪問頻次限制,一天幾百次還是沒啥問題,太快或者太多次訪問就會被封24小時。

    二、xposed + python 怎么爬取微信朋友圈的數(shù)據(jù)

    有JAVA的,你參考一下

    主要思路

    從UI獲取文本信息是最為簡單的方法,于是應該優(yōu)先逆向UI代碼部分。

    逆向微信apk

    首先解包微信apk,用dex2jar反編譯classes.dex,然后用JD-GUI查看jar源碼。當然,能看到的源碼都是經(jīng)過高度混淆的。但是,繼承自安卓重要組件(如Activity、Service等)的類名無法被混淆,于是還是能從中看到點東西。

    首先定位到微信APP package。我們知道這個是 com.tencent.mm

    。

    在 com.tencent.mm

    中,我們找到一個 ui

    包,有點意思。

    展開 com.tencent.mm.ui

    ,發(fā)現(xiàn)多個未被混淆的類,其中發(fā)現(xiàn) MMBaseActivity

    直接繼承自 Activity

    , MMFragmentActivity

    繼承自 ActionBarActivity

    , MMActivity

    繼承自 MMFragmentActivity

    ,并且 MMActivity

    是微信中大多數(shù)Activity的父類:

    public class MMFragmentActivity

    extends ActionBarActivity

    implements SwipeBackLayout.a, b.a {

    ...

    }

    public abstract class MMActivity

    extends MMFragmentActivity {

    ...

    }

    public class MMBaseActivity

    extends Activity {

    ...

    }

    現(xiàn)在需要找出朋友圈的Activity,為此要用Xposed hook MMActivity

    創(chuàng)建一個Xposed模塊

    參考 [TUTORIAL]Xposed module devlopment

    ,創(chuàng)建一個Xposed項目。

    簡單Xposed模塊的基本思想是:hook某個APP中的某個方法,從而達到讀寫數(shù)據(jù)的目的。

    小編嘗試hook com.tencent.mm.ui.MMActivity.setContentView

    這個方法,并打印出這個Activity下的全部TextView內(nèi)容。那么首先需要遍歷這個Activity下的所有TextView,遍歷ViewGroup的方法參考了SO的以下代碼:

    private void getAllTextViews(final View v) {

    if (v instanceof ViewGroup) {

    ViewGroup vg = (ViewGroup) v;

    for (int i = 0; i < vg.getChildCount(); i++) {

    View child = vg.getChildAt(i);

    getAllTextViews(child);

    }

    } else if (v instanceof TextView ) {

    dealWithTextView((TextView)v); //dealWithTextView(TextView tv)方法:打印TextView中的顯示文本

    }

    }

    Hook MMActivity.setContentView

    的關(guān)鍵代碼如下:

    findAndHookMethod("com.tencent.mm.ui.MMActivity", lpparam.classLoader, "setContentView", View.class, new XC_MethodHook() {

    ...

    });

    在findAndHookMethod方法中,第一個參數(shù)為完整類名,第三個參數(shù)為需要hook的方法名,其后若干個參數(shù)分別對應該方法的各形參類型。在這里, Activity.setContentView(View view)

    方法只有一個類型為 View

    的形參,因此傳入一個 View.class

    現(xiàn)在,期望的結(jié)果是運行時可以從Log中讀取到每個Activity中的所有的TextView的顯示內(nèi)容。

    但是,因為View中的數(shù)據(jù)并不一定在 setContentView()

    時就加載完畢,因此小編的實驗結(jié)果是,log中啥都沒有。

    意外的收獲

    當切換到朋友圈頁面時,Xposed模塊報了一個異常,異常源從 com.tencent.mm.plugin.sns.ui.SnsTimeLineUI

    這個類捕捉到。從類名上看,這個很有可能是朋友圈首頁的UI類。展開這個類,發(fā)現(xiàn)更多有趣的東西:

    這個類下有個子類 a

    (被混淆過的類名),該子類下有個名為 gyO

    的 ListView

    類的實例。我們知道, ListView

    是顯示列表類的UI組件,有可能就是用來展示朋友圈的列表。

    順藤摸瓜

    那么,我們先要獲得一個 SnsTimeLineUI.a.gyO

    的實例。但是在這之前,要先獲得一個 com.tencent.mm.plugin.sns.ui.SnsTimeLineUI.a

    的實例。繼續(xù)搜索,發(fā)現(xiàn) com.tencent.mm.plugin.sns.ui.SnsTimeLineUI

    有一個名為 gLZ

    的 SnsTimeLineUI.a

    實例,那么我們先取得這個實例。

    經(jīng)過測試, com.tencent.mm.plugin.sns.ui.SnsTimeLineUI.a(boolean, boolean, String, boolean)

    這個方法在每次初始化微信界面的時候都會被調(diào)用。因此我們將hook這個方法,并從中取得 gLZ

    。

    findAndHookMethod("com.tencent.mm.plugin.sns.ui.SnsTimeLineUI", lpparam.classLoader, "a", boolean.class, boolean.class, String.class, boolean.class, new XC_MethodHook() {

    @Override

    protected void afterHookedMethod(MethodHookParam param) throws Throwable {

    XposedBridge.log("Hooked. ");

    Object currentObject = param.thisObject;

    for (Field field : currentObject.getClass().getDeclaredFields()) { //遍歷類成員

    field.setAccessible(true);

    Object value = field.get(currentObject);

    if (field.getName().equals("gLZ")) {

    XposedBridge.log("Child A found.");

    childA = value;

    //這里獲得了gLZ

    ...

    }

    }

    }

    });

    現(xiàn)在取得了 SnsTimeLineUI.a

    的一個實例 gLZ

    ,需要取得這個類下的 ListView

    類型的 gyO

    屬性。

    private void dealWithA() throws Throwable{

    if (childA == null) {

    return;

    }

    for (Field field : childA.getClass().getDeclaredFields()) { //遍歷屬性

    field.setAccessible(true);

    Object value = field.get(childA);

    if (field.getName().equals("gyO")) { //取得了gyO

    ViewGroup vg = (ListView)value;

    for (int i = 0; i < vg.getChildCount(); i++) { //遍歷這個ListView的每一個子View

    ...

    View child = vg.getChildAt(i);

    getAllTextViews(child); //這里調(diào)用上文的getAllTextViews()方法,每一個子View里的所有TextView的文本

    ...

    }

    }

    }

    }

    現(xiàn)在已經(jīng)可以將朋友圈頁面中的全部文字信息打印出來了。我們需要根據(jù)TextView的子類名判斷這些文字是朋友圈內(nèi)容、好友昵稱、點贊或評論等。

    private void dealWithTextView(TextView v) {

    String className = v.getClass().getName();

    String text = ((TextView)v).getText().toString().trim().replaceAll("\n", " ");

    if (!v.isShown())

    return;

    if (text.equals(""))

    return;

    if (className.equals("com.tencent.mm.plugin.sns.ui.AsyncTextView")) {

    //好友昵稱

    ...

    }

    else if (className.equals("com.tencent.mm.plugin.sns.ui.SnsTextView")) {

    //朋友圈文字內(nèi)容

    ...

    }

    else if (className.equals("com.tencent.mm.plugin.sns.ui.MaskTextView")) {

    if (!text.contains(":")) {

    //點贊

    ...

    } else {

    //評論

    ...

    }

    }

    }

    自此,我們已經(jīng)從微信APP里取得了朋友圈數(shù)據(jù)。當然,這部分抓取代碼需要定時執(zhí)行。因為從 ListView

    中抓到的數(shù)據(jù)只有當前顯示在屏幕上的可見部分,為此需要每隔很短一段時間再次執(zhí)行,讓用戶在下滑加載的過程中抓取更多數(shù)據(jù)。

    剩下的就是數(shù)據(jù)分類處理和格式化輸出到文件,受本文篇幅所限不再贅述,詳細實現(xiàn)可參考作者GitHub上的源碼。

    三、怎樣通過app查看微信被誰登錄過

    微信里面有訂閱號、可以自己查看。

    四、微信聊天記錄如何提取出來

    微信聊天記錄提取出來的具體操作如下:

    工具:華為手機。微信APP

    1、打開手機,登錄微信主頁面,點擊右下角的“我”。

    2、點擊界面中的【設(shè)置】選項卡。

    3、在【設(shè)置】界面中,選擇【聊天】選項卡。

    4、在接下來彈出的界面中,選擇【聊天記錄備份與遷移】選項卡,然后就可以導出微信聊天記錄了。

    以上就是關(guān)于抓取微信APP登錄數(shù)據(jù)相關(guān)問題的回答。希望能幫到你,如有更多相關(guān)問題,您也可以聯(lián)系我們的客服進行咨詢,客服也會為您講解更多精彩的知識和內(nèi)容。


    推薦閱讀:

    特征抓取SEO(特征搜索算法)

    抓取百度關(guān)鍵詞電話(抓取百度關(guān)鍵詞電話的方法)

    關(guān)鍵詞每半小時抓取(關(guān)鍵詞時長)

    學生形象

    轉(zhuǎn)mbr后無法進入系統(tǒng)(mbr轉(zhuǎn)guid后無法啟動)