分享好友 行情首页 行情分类 切换频道
带大家写一波微信公众号的爬取!谁说微信爬不了的!
2024-12-19 17:44  浏览:88

python版本  3.6.4
相关模块
pdfkit模块
requests模块
以及一些Python自带的模块。
抓包工具 fiddler


  1. python 环境
    安装Python并添加到环境变量,pip安装需要的相关模块即可。
  2. fiddler 环境
    去官网下载最新版本的安装包直接安装。
    fiddler官网

首先,我们打开fiddler这个抓包软件,其界面如下


然后,我们设置一下过滤规则以过滤掉没用的数据包,因为我们只想抓取微信相关的数据包而已,而不想其他没用的数据包干扰我们的分析,就像这样


接着我们在电脑端登录微信,并随便找个公众号,查看它的历史文章列表。就像这样


不断滚动鼠标滚轮,以查看该公众号更多的历史文章数据。此时,我们可以在fiddler里看到出现了类似如下图所示的情况

显然,红框里的https请求应该就是获得该微信公众号发的文章相关的数据的请求了。现在,我们来分析一下这个请求。显然,该请求的链接地址构成为


接着看看请求头,请求头的话在这能看到


感觉有个user-agent就足够了

headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1295.400 QQBrowser/9.0.2524.400 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2875.116 Safari/537.36 NetType/WIFI MicroMessenger/7.0.5 WindowsWechat'
         }
123

接着看看cookies,在这(应该直接复制到代码里就行了)

最后,再看看发送这个请求需要携带哪些参数吧,在这


action
__biz
f
offset
count
is_ok
scene
uin
key
pass_ticket
wxtoken
appmsg_token
x5

经过测试,我们可以发现如下参数是可以固定的

action
f
is_ok
scene
uin
key
wxtoken
x5

其他参数的含义我们则可以根据经验和简单的测试进行判断

1.offset
控制翻页的偏移量参数
2.count
每页的文章数量
3.__biz
公众号标识, 不同的__biz对应不同的公众号
4.pass_ticket
应该是微信登录之后返回的参数吧,
去年尝试模拟登录微信网页版的时候看到返回的参数里就好像有它,
但是现在微信网页版已经被官方封了T_T。
5.appmsg_token
应该也是微信登录之后的一个标识参数吧, 而且和阅读的微信公众号
有关,查看不同的微信公众号时该值也是不同的。

前面三个可变参数都好解决,后面两个参数似乎就比较难办了。不过经过测试,我们可以发现pass_ticket其实是一个可有可无的参数,所以我们可以不管它。而appmsg_token的有效期至少有10几个小时,这段时间足够我们爬取目标公众号的所有文章了,所以直接复制过来就可以了,没必要浪费时间分析这玩意(随便想想也应该知道白嫖腾讯肯定没那么容易的T_T)。写个代码简单测试一下

import requests

session = requests.Session()
session.headers.update(headers)
session.cookies.update(cookies)
profile_url = '前面抓包得到的请求地址'
biz = 'MzAwNTA5NTYxOA=='
pass_ticket = ''
appmsg_token = '1055_YAmuAw2QG7dM3aTwSVZVqgtRdct6ilAMTwlz7g'
params = {
            'action': 'getmsg',
            '__biz': biz,
            'f': 'json',
            'offset': '0',
            'count': '10',
            'is_ok': '1',
            'scene': '123',
            'uin': '777',
            'key': '777',
            'pass_ticket': pass_ticket,
            'wxtoken': '',
            'appmsg_token': appmsg_token,
            'x5': '0'
        }
res = session.get(profile_url, params=params, verify=False)
print(res.text)

运行之后可以发现返回的数据如下


看来是没啥问题,重新调整封装一下代码,就可以爬取该公众号所有文章的链接啦。具体而言,核心代码实现如下

'''获得所有文章的链接'''
def __getArticleLinks(self):
    print('[INFO]: 正在获取目标公众号的所有文章链接...')
    fp = open('links_tmp.json', 'w', encoding='utf-8')
    article_infos = {}
    params = {
                'action': 'getmsg',
                '__biz': self.cfg.biz,
                'f': 'json',
                'offset': '0',
                'count': '10',
                'is_ok': '1',
                'scene': '123',
                'uin': '777',
                'key': '777',
                'pass_ticket': self.cfg.pass_ticket,
                'wxtoken': '',
                'appmsg_token': self.cfg.appmsg_token,
                'x5': '0'
            }
    while True:
        res = self.session.get(self.profile_url, params=params, verify=False)
        res_json = res.json()
        can_msg_continue = res_json.get('can_msg_continue', '')
        next_offset = res_json.get('next_offset', 10)
        general_msg_list = json.loads(res_json.get('general_msg_list', '{}'))
        params.update({'offset': next_offset})
        for item in general_msg_list['list']:
            app_msg_ext_info = item.get('app_msg_ext_info', {})
            if not app_msg_ext_info: continue
            title = app_msg_ext_info.get('title', '')
            content_url = app_msg_ext_info.get('content_url', '')
            if title and content_url:
                article_infos[title] = content_url
            if app_msg_ext_info.get('is_multi', '') == 1:
                for article in app_msg_ext_info.get('multi_app_msg_item_list', []):
                    title = article.get('title', '')
                    content_url = article.get('content_url', '')
                    if title and content_url:
                        article_infos[title] = content_url
        if can_msg_continue != 1: break
        else: time.sleep(1+random.random())
    json.dump(article_infos, fp)
    fp.close()
    print('[INFO]: 已成功获取目标公众号的所有文章链接, 数量为%s...' % len(list(article_infos.keys())))



运行之后,我们就可以获得目标公众号的所有文章链接啦

 

现在,我们只需要根据这些文章链接来爬取文章内容就行啦。这里我们借助python的第三方包pdfkit来实现将每篇文章都保存为pdf格式的文件。具体而言,核心代码实现如下

'''下载所有文章'''
def __downloadArticles(self):
    print('[INFO]: 开始爬取目标公众号的所有文章内容...')
    if not os.path.exists(self.savedir):
        os.mkdir(self.savedir)
    fp = open('links_tmp.json', 'r', encoding='utf-8')
    article_infos = json.load(fp)
    for key, value in article_infos.items():
        print('[INFO]: 正在抓取文章 ——> %s' % key)
        pdfkit.from_url(value, os.path.join(self.savedir, key+'.pdf'), configuration=pdfkit.configuration(wkhtmltopdf=self.cfg.wkhtmltopdf_path))
    print('[INFO]: 已成功爬取目标公众号的所有文章内容...')

注意,使用pdfkit前需要先安装wkhtmltox。如下图所示


运行的效果大概是这样子的

带大家写一波微信公众号的爬取!谁说微信爬不了的!

 


根据自己的抓包结果修改cfg.py文件

## cfg.py
# 目标公众号标识
biz = 'MzAwNTA5NTYxOA=='
# 微信登录后的一些标识参数
pass_ticket = ''
appmsg_token = '1055_YAmuAw2QG7dM3aTwSVZVqgtRdct6ilAMTwlz7g~~'
# 安装的wkhtmltopdf.exe文件路径
wkhtmltopdf_path = r'D:Program Fileswkhtmltopdfbinwkhtmltopdf.exe'
12345678
## articlesSpider.py
import os
import time
import json
import pdfkit
import random
import requests
import warnings
warnings.filterwarnings('ignore')


'''微信公众号文章爬取类'''
class articlesSpider(object):
    def __init__(self, cfg, **kwargs):
        self.cfg = cfg
        self.session = requests.Session()
        self.__initialize()
    '''外部调用'''
    def run(self):
        self.__getArticleLinks()
        self.__downloadArticles()
    '''获得所有文章的链接'''
    def __getArticleLinks(self):
        print('[INFO]: 正在获取目标公众号的所有文章链接...')
        fp = open('links_tmp.json', 'w', encoding='utf-8')
        article_infos = {}
        params = {
                    'action': 'getmsg',
                    '__biz': self.cfg.biz,
                    'f': 'json',
                    'offset': '0',
                    'count': '10',
                    'is_ok': '1',
                    'scene': '123',
                    'uin': '777',
                    'key': '777',
                    'pass_ticket': self.cfg.pass_ticket,
                    'wxtoken': '',
                    'appmsg_token': self.cfg.appmsg_token,
                    'x5': '0'
                }
        while True:
            res = self.session.get(self.profile_url, params=params, verify=False)
            res_json = res.json()
            can_msg_continue = res_json.get('can_msg_continue', '')
            next_offset = res_json.get('next_offset', 10)
            general_msg_list = json.loads(res_json.get('general_msg_list', '{}'))
            params.update({'offset': next_offset})
            for item in general_msg_list['list']:
                app_msg_ext_info = item.get('app_msg_ext_info', {})
                if not app_msg_ext_info: continue
                title = app_msg_ext_info.get('title', '')
                content_url = app_msg_ext_info.get('content_url', '')
                if title and content_url:
                    article_infos[title] = content_url
                if app_msg_ext_info.get('is_multi', '') == 1:
                    for article in app_msg_ext_info.get('multi_app_msg_item_list', []):
                        title = article.get('title', '')
                        content_url = article.get('content_url', '')
                        if title and content_url:
                            article_infos[title] = content_url
            if can_msg_continue != 1: break
            else: time.sleep(1+random.random())
        json.dump(article_infos, fp)
        fp.close()
        print('[INFO]: 已成功获取目标公众号的所有文章链接, 数量为%s...' % len(list(article_infos.keys())))
    '''下载所有文章'''
    def __downloadArticles(self):
        print('[INFO]: 开始爬取目标公众号的所有文章内容...')
        if not os.path.exists(self.savedir):
            os.mkdir(self.savedir)
        fp = open('links_tmp.json', 'r', encoding='utf-8')
        article_infos = json.load(fp)
        for key, value in article_infos.items():
            print('[INFO]: 正在抓取文章 ——> %s' % key)
            key = key.replace('\', '').replace('/', '').replace(':', '').replace('', '') 
                     .replace('*', '').replace('?', '').replace('', '').replace('“', '')  
                     .replace('"', '').replace('<', '').replace('>', '').replace('|', '_')
            pdfkit.from_url(value, os.path.join(self.savedir, key+'.pdf'), configuration=pdfkit.configuration(wkhtmltopdf=self.cfg.wkhtmltopdf_path))
        print('[INFO]: 已成功爬取目标公众号的所有文章内容...')
    '''类初始化'''
    def __initialize(self):
        self.headers = {
                        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1295.400 QQBrowser/9.0.2524.400 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2875.116 Safari/537.36 NetType/WIFI MicroMessenger/7.0.5 WindowsWechat'
                    }
        self.cookies = {
                        'wxuin': '913366226',
                        'devicetype': 'iPhoneiOS13.3.1',
                        'version': '17000c27',
                        'lang': 'zh_CN',
                        'pass_ticket': self.cfg.pass_ticket,
                        'wap_sid2': 'CNK5w7MDElxvQU1fdWNuU05qNV9lb2t3cEkzNk12ZHBsNmdXX3FETlplNUVTNzVfRmwyUUtKZzN4QkxJRUZIYkMtMkZ1SDU5S0FWQmtSNk9mTTQ1Q1NDOXpUYnJQaDhFQUFBfjDX5LD0BTgNQJVO'
                    }
        self.profile_url = 'https://mp.weixin.qq.com/mp/profile_ext'
        self.savedir = 'articles'
        self.session.headers.update(self.headers)
        self.session.cookies.update(self.cookies)


'''run'''
if __name__ == '__main__':
    import cfg
    spider = articlesSpider(cfg)
    spider.run()

简单吧。不会的话就加我企鹅群领取视频教程和源代码 :841625887

    以上就是本篇文章【带大家写一波微信公众号的爬取!谁说微信爬不了的!】的全部内容了,欢迎阅览 ! 文章地址:http://w.yusign.com/quote/1663.html 
     行业      资讯      企业新闻      行情      企业黄页      同类资讯      网站地图      返回首页 述古往 http://w.yusign.com/mobile/ , 查看更多   
最新新闻
CASETiFY推出全新iPhone 14系列手机壳:个性化定制 秀出自在真我定制手机壳「CASETiFY推出全新iPhone 14系列手机壳:个性化定制 秀出自在真我」
  (2022年9月8日,上海) 作为深受千禧一代、Z世代和好莱坞名人喜爱的国际潮流生活方式品牌,CASETiFY于今日推出全新升级的iP
专家教你用手机找出针孔摄像头手机摄像「专家教你用手机找出针孔摄像头」
  国庆假期快到了,有出游计划的小伙伴们是否担心投宿的酒店被安装了摄像头?针孔摄像头在暗处偷窥人们的隐私,让人胆战心惊,
追踪到底|不续费会员就不让结账?山姆会员商店被多名消费者投诉抢手机「追踪到底|不续费会员就不让结账?山姆会员商店被多名消费者投诉」
来源:封面新闻封面新闻记者近日,封面新闻《追踪到底》栏目和云投诉平台接到多地山姆会员商店的消费者反映,称在山姆会员商店会
手机选购指南:如何根据硬件配置和使用需求挑选适合你的手机手机怎么选「手机选购指南:如何根据硬件配置和使用需求挑选适合你的手机」
选择一款适合自己的手机不仅仅是满足日常通讯需求,更是提升生活品质的重要一环。面对市场上琳琅满目的手机品牌和型号,我们该如
ios云手机哪个便宜好用?ios好用的云手机排行榜前十名手机排行前十名「ios云手机哪个便宜好用?ios好用的云手机排行榜前十名」
身为喜爱用苹果手机畅玩安卓游戏的 ios 用户,挑选便宜好用的 ios 云手机并非易事。市场产品众多,究竟哪款能脱颖而出?下面就为
《中考四轮复习》和《万唯》哪个好 ?手机搜狐网「《中考四轮复习》和《万唯》哪个好 ?」
初三这一年最看重的就是总复习了,特别是一轮复习除了紧跟老师的复习节奏,自己也必须有一本适合自己的总复习资料自主复习。 市
steam手机版怎么下游戏steam手机版下载「steam手机版怎么下游戏」
随着移动设备的普及,Steam平台也推出了其手机版应用,让玩家能够随时随地浏览游戏、管理库存并享受游戏乐趣。然而,对于许多新
169元购入会“说话的”车载无线充电手机支架 使用感受分享车载手机支架「169元购入会“说话的”车载无线充电手机支架 使用感受分享」
随着媳妇喜提华为P40,她原来的mate 20 pro也正式在我这里服役了,相比我以前的苹果8,mate 20 pro的功能对我来说还是比较新鲜的
京剧名篇——贵妃醉酒手机搜狐网「京剧名篇——贵妃醉酒」
京剧名篇——贵妃醉酒 海岛冰轮初转腾 见玉兔,见玉兔又早东升 那冰轮离海岛,乾坤分外明 皓月当空 恰便似嫦娥离月宫,奴似嫦娥
原创手机的监听开关要尽快关闭,不然你看过什么,手机就向你推送什么关闭手机「原创手机的监听开关要尽快关闭,不然你看过什么,手机就向你推送什么」
朋友们大家好,我是小俊,今天小俊给大家分享一下如何关闭手机的监听开关,来保护我们的隐私!如果说我们不关闭这个开关的话,那
本企业新闻
推荐企业新闻
发表评论
0评