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

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

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

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

    本文目錄:

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

    一、如何抓取微信所有公眾號(hào)最新文章

    經(jīng)常有朋友需要幫忙做公眾號(hào)文章爬取,這次來(lái)做一個(gè)各種方法的匯總說(shuō)明。

    目前爬取微信公眾號(hào)的方法主要有3種:

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

    • 通過(guò)微信公眾平臺(tái)引用文章接口

    • 通過(guò)抓包程序,分析微信app訪問(wèn)公眾號(hào)文章的接口

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

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

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

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

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

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

    通過(guò)微信公眾平臺(tái)引用文章接口

    這個(gè)接口比較隱蔽而且沒(méi)法匿名訪問(wèn),所有得有一個(gè)公眾號(hào),建議新注冊(cè)一個(gè)公眾號(hào)比較好,免得被封。

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

    點(diǎn)擊這個(gè)超鏈接按鈕,就會(huì)彈出一個(gè)對(duì)話框,鏈接輸入方式這一項(xiàng)選中 查找文章,如下圖:

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

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

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

    由于微信公眾平臺(tái)登錄驗(yàn)證比較嚴(yán)格,輸入密碼之后還必須要手機(jī)掃碼確認(rèn)才能登錄進(jìn)去,所以最好還是使用 selenium做自動(dòng)化比較好。具體微信接口的分析過(guò)程我就不列了,直接貼代碼了:

    • import re

    • import time

    • import random

    • import traceback

    • import requests

    • from selenium import webdriver

    • class Spider(object):

    • '''

    • 微信公眾號(hào)文章爬蟲(chóng)

    • '''

    • def __init__(self):

    • # 微信公眾號(hào)賬號(hào)

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

    • # 微信公眾號(hào)密碼

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

    • # 訪問(wèn)微信公眾平臺(tái)

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

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

    • 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)首頁(yè)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'

    • }

    • # 打開(kāi)搜索微信公眾號(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', # 不同頁(yè),此參數(shù)變化,變化規(guī)則為每頁(yè)加5

    • 'count': '5',

    • 'query': '',

    • 'type': '9'

    • }

    • self.log('正在查詢公眾號(hào)[ %s ]相關(guān)文章' % nickname)

    • # 打開(kāi)搜索的微信公眾號(hào)文章列表頁(yè)

    • 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í)使用,沒(méi)有做分頁(yè)查詢之類。實(shí)測(cè)過(guò)接口存在訪問(wèn)頻次限制,一天幾百次還是沒(méi)啥問(wèn)題,太快或者太多次訪問(wèn)就會(huì)被封24小時(shí)。

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

    有JAVA的,你參考一下

    主要思路

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

    逆向微信apk

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

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

    。

    在 com.tencent.mm

    中,我們找到一個(gè) ui

    包,有點(diǎn)意思。

    展開(kāi) com.tencent.mm.ui

    ,發(fā)現(xiàn)多個(gè)未被混淆的類,其中發(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)建一個(gè)Xposed模塊

    參考 [TUTORIAL]Xposed module devlopment

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

    簡(jiǎn)單Xposed模塊的基本思想是:hook某個(gè)APP中的某個(gè)方法,從而達(dá)到讀寫(xiě)數(shù)據(jù)的目的。

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

    這個(gè)方法,并打印出這個(gè)Activity下的全部TextView內(nèi)容。那么首先需要遍歷這個(gè)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方法中,第一個(gè)參數(shù)為完整類名,第三個(gè)參數(shù)為需要hook的方法名,其后若干個(gè)參數(shù)分別對(duì)應(yīng)該方法的各形參類型。在這里, Activity.setContentView(View view)

    方法只有一個(gè)類型為 View

    的形參,因此傳入一個(gè) View.class

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

    但是,因?yàn)閂iew中的數(shù)據(jù)并不一定在 setContentView()

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

    意外的收獲

    當(dāng)切換到朋友圈頁(yè)面時(shí),Xposed模塊報(bào)了一個(gè)異常,異常源從 com.tencent.mm.plugin.sns.ui.SnsTimeLineUI

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

    這個(gè)類下有個(gè)子類 a

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

    的 ListView

    類的實(shí)例。我們知道, ListView

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

    順藤摸瓜

    那么,我們先要獲得一個(gè) SnsTimeLineUI.a.gyO

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

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

    有一個(gè)名為 gLZ

    的 SnsTimeLineUI.a

    實(shí)例,那么我們先取得這個(gè)實(shí)例。

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

    這個(gè)方法在每次初始化微信界面的時(shí)候都會(huì)被調(diào)用。因此我們將hook這個(gè)方法,并從中取得 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

    的一個(gè)實(shí)例 gLZ

    ,需要取得這個(gè)類下的 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++) { //遍歷這個(gè)ListView的每一個(gè)子View

    ...

    View child = vg.getChildAt(i);

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

    ...

    }

    }

    }

    }

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

    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(":")) {

    //點(diǎn)贊

    ...

    } else {

    //評(píng)論

    ...

    }

    }

    }

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

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

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

    三、怎樣通過(guò)app查看微信被誰(shuí)登錄過(guò)

    微信里面有訂閱號(hào)、可以自己查看。

    四、微信聊天記錄如何提取出來(lái)

    微信聊天記錄提取出來(lái)的具體操作如下:

    工具:華為手機(jī)。微信APP。

    1、打開(kāi)手機(jī),登錄微信主頁(yè)面,點(diǎn)擊右下角的“我”。

    2、點(diǎn)擊界面中的【設(shè)置】選項(xiàng)卡。

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

    4、在接下來(lái)彈出的界面中,選擇【聊天記錄備份與遷移】選項(xiàng)卡,然后就可以導(dǎo)出微信聊天記錄了。

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


    推薦閱讀:

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

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

    關(guān)鍵詞每半小時(shí)抓?。P(guān)鍵詞時(shí)長(zhǎng))

    學(xué)生形象

    轉(zhuǎn)mbr后無(wú)法進(jìn)入系統(tǒng)(mbr轉(zhuǎn)guid后無(wú)法啟動(dòng))