如何爬取微信公众号文章(一)

article/2025/10/6 16:25:19

微信公众号是目前最为流行的自媒体之一,上面有大量的内容,如何将自己感兴趣的公众号内容爬取下来,离线浏览,或者作进一步的分析呢?
下面我们讨论一下微信公众号文章的爬取。
image.png

环境搭建

  • windows 7 x64
  • python3.7 (Anaconda 3)
  • vscode编辑器
  • Firefox开发版

爬虫原理分析

首先网页登陆微信公众平台(https://mp.weixin.qq.com/),登陆成功后,点击新建群发->自建图文,插入超连接在如下的对话框中,点击选择其他公众号。
编辑超链接
在弹出的编辑超链接的对话框中,输入想要爬取的公众号名字,回车
搜索公众号
下拉列表中第一个就是我们想找的,点击它,弹出的这个公众号的文章列表,是按照时间排序的。
文章列表
我们看一下这个过程中前后端交互的HTTP请求和响应。

检索公众号

请求url: https://mp.weixin.qq.com/cgi-bin/searchbiz
方法: GET
提交的参数为

{"action": "search_biz","begin": "0","count": "5","query": "地球知识局","token": "138019412","lang": "zh_CN","f": "json","ajax": "1"
}

请求中的字段

action 动作
begin 列表的起始
count 列表的数目
query 查询的字符串
f 参数格式 这里为json
ajax 应该代码ajax请求
lang 语言 这里是中文
token 这应该是授权信息,下文会深究

得到的响应为

{"base_resp": {"ret": 0,"err_msg": "ok"},"list": [{"fakeid": "MzI1ODUzNjQ1Mw==","nickname": "地球知识局","alias": "diqiuzhishiju","round_head_img": "http://mmbiz.qpic.cn/mmbiz_png/DCftNYRGoKWLHFETxuTzGBguTwAibl0p8BpXmNIkBTmNth2Vd6vEWibtT8mLYWG6e5aiaa97u5LmjhbXn19a8Cr6g/0?wx_fmt=png","service_type": 1},{"fakeid": "MzU5MjI3MzIyMg==","nickname": "地球知识局库","alias": "","round_head_img": "http://mmbiz.qpic.cn/mmbiz_png/b5kRqlMaRNHJnJ1ibFUPOichbvtVGk7CWicj406ZAccBuOpr2JibShHSAvUN7iaSuQj3rN66P8akeKa63rjy11NNkicw/0?wx_fmt=png","service_type": 2},{},{},{}],"total": 45
}

响应中各字段的含义不难看出

fakeid 为该公众号的唯一的id,为一串bs64编码
nikename 为公众号的名称
alias 为别名
round_head_img 为圆形logo的url
service_type 服务类型 不太清楚 没必要深究用不到

获取公众号文章列表

请求网址:https://mp.weixin.qq.com/cgi-bin/appmsg
请求方法:GET
提交的参数:

{"action": "list_ex","begin": "0","count": "5","fakeid": "MzI1ODUzNjQ1Mw==","type": "9","query": "", "token": "138019412","lang": "zh_CN","f": "json","ajax": "1"
}

action 行为
begin 列表开始索引
count 列表返回的公众号的时间区间长度,如5表示返回5天的数据
fakeid 这个公众号的ID
type 不知道
query 检索的关键字,这里为空
token 用户的token
lang 语言
f 数据格式,这里为json
ajax

响应为

{"app_msg_cnt": 919,"app_msg_list": [{"aid": "2247518136_1","appmsgid": 2247518136,"cover": "https://mmbiz.qlogo.cn/mmbiz_jpg/DCftNYRGoKWG0USHVfs1FG2pGKfz0BMUI3FLibHTrYe1a7WMKzZnazCKDJ9OUfuibGbewFqIiakic8MEqDkNiaXHH7w/0?wx_fmt=jpeg","create_time": 1578235906,"digest": "三不管地带容易出问题","is_pay_subscribe": 0,"item_show_type": 0,"itemidx": 1,"link": "http://mp.weixin.qq.com/s?__biz=MzI1ODUzNjQ1Mw==&mid=2247518136&idx=1&sn=812ec79199ae793f28770287969d0f2b&chksm=ea0462d2dd73ebc40f6ecc4f1f52fb2a3e0c798ca152aa89cc42b8e77ef6e54234695ad43025#rd","tagid": [],"title": "肆虐非洲的“博科圣地”究竟是什么?","update_time": 1578235905},{},{}],"base_resp": {"err_msg": "ok","ret": 0}
}

响应的字段

app_msg_cnt 表示这个公众号已经发布了919次文章,不代表919篇文章
aid 文章唯一的id,应该是
appmsgid 代表一次群发,如三篇文章是一次性群发的,其appmsgid相同
cover 文章封面图片的url
create_time 创建时间戳
digest 文章的摘要信息
is_pay_subscribe
item_show_type
itemidx 在这次群发中的序号
link 文章的url
tagid 为一个列表
title 文章的标题
update_time 文章更新的时间戳
这些已经包含了一篇文章的元数据了。

token从哪儿来

上面的GET方法提交的参数有中都有个token字段,这个字段的用途应该鉴权用的,这个值从哪儿来的?我们在前面的HTTP请求中找,发现几乎所有的请求中的都带有这个token,我猜测这个token是用户登陆时从后端返回来的。
为了印证这个判断,重新登陆一次,发现了有这样的一个HTTP请求。
请求网址:https://mp.weixin.qq.com/cgi-bin/bizlogin?action=login
请求方法:POST
表单数据:

{"userlang": "zh_CN","redirect_url": "","token": "","lang": "zh_CN","f": "json","ajax": "1"
}

响应:

{"base_resp": {"err_msg": "ok","ret": 0},"redirect_url": "/cgi-bin/home?t=home/index&lang=zh_CN&token=1193797244"
}

后端返回了一个重定向的uri,其中就包含了token的值。
完成这个请求后,页面进行了重定向,并且以后的每次请求都有会有lang=zh_CN&token=xxxx这两个参数。

代码实现

完成了上面这些分析,下面我们进行代码实现。

# -*- coding:utf-8 -*-
# written by wlj @2020-1-6 23:12:47 
#功能:爬取一个公众号的所有历史文章存入数据库
#用法:python wx_spider.py [公众号名称] 如python wx_spider.py 地球知识局
import time
import json
import requests,re,sys
from requests.packages import urllib3
from pymongo import MongoClient
urllib3.disable_warnings()#全局变量
s = requests.Session()
headers = {'User-Agent':"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0","Host": "mp.weixin.qq.com",'Referer':'https://mp.weixin.qq.com/'
}
#cookies 字符串,这是从浏览器中拷贝出来的字符串,略过不讲
cookie_str = "xxxx"
cookies = {}#加载cookies,将字符串格式的cookies转化为字典形式
def load_cookies():global cookie_str,cookiesfor item in cookie_str.split(';'):sep_index = item.find('=') cookies[item[:sep_index]] =item[sep_index+1:]#爬虫主函数
def spider():#本地的mongodb数据库mongo = MongoClient('127.0.0.1',27017).wx.gzh#加载cookiesload_cookies()#访问官网主页url = 'https://mp.weixin.qq.com'res = s.get(url=url,headers=headers,cookies = cookies,verify=False)if res.status_code ==  200:#由于加载了cookies,相当于已经登陆了,系统作了重定义,response的url中含有我们需要的tokenprint(res.url)#获得tokentoken = re.findall(r'.*?token=(\d+)',res.url)if token:token = token[0]else:#没有token的话,说明cookies过时了,没有登陆成功,退出程序print('登陆失败')returnprint('token',token)#检索公众号url = 'https://mp.weixin.qq.com/cgi-bin/searchbiz'data = {"action": "search_biz","begin": "0","count": "5","query": sys.argv[1],"token": token,"lang": "zh_CN","f": "json","ajax": "1"}res = s.get(url=url,params = data,cookies=cookies,headers=headers,verify=False)if res.status_code == 200:#搜索结果的第一个往往是最准确的#提取它的fakeidfakeid = res.json()['list'][0]['fakeid']print('fakeid',fakeid)page_size = 5page_count = 1cur_page = 1#分页请求文章列表while cur_page <= page_count:url = 'https://mp.weixin.qq.com/cgi-bin/appmsg'data = {"action": "list_ex","begin": str(page_size*(cur_page-1)),"count": str(page_size),"fakeid": fakeid,"type": "9","query": "", "token": token,"lang": "zh_CN","f": "json","ajax": "1"}res = s.get(url=url,params = data,cookies=cookies,headers=headers,verify=False)if res.status_code == 200:print(res.json())print('cur_page',cur_page)#文章列表位于app_msg_list字段中app_msg_list = res.json()['app_msg_list']for item in app_msg_list:#通过更新时间戳获得文章的发布日期item['post_date'] = time.strftime("%Y-%m-%d",time.localtime(int(item['update_time'])))#插入数据库,如果已经存在同aid的话,更新,不存在,插入mongo.update_one({'aid':item['aid']},{"$set":item},upsert=True)print(item['post_date'],item['title'])if cur_page == 1:#若是第1页,计算总的分页数#总的日期数,每page_size天的文章为一页app_msg_cnt = res.json()['app_msg_cnt']print('app_msg_cnt',app_msg_cnt)#计算总的分页数if app_msg_cnt % page_size == 0:page_count = int(app_msg_cnt / page_size)else:page_count = int(app_msg_cnt / page_size) + 1#当前页面数+1cur_page += 1print('完成!')spider()

结果

爬取的结果

可以看到,所有文章的元数据已经存入数据库了。
下一节,我们讲如何利用文章的url来爬取文章内容,这个比较简单。
这儿还存在一个问题,腾讯的这个接口有频率限制,当爬取的次数太多,频率太快时,就请求不到数据了,会返回这样的信息。

{'base_resp': {'err_msg': 'freq control', 'ret': 200013}}

至少间隔一天,这个账号才能继续爬取,不知道如何破解。


http://chatgpt.dhexx.cn/article/HDRIt1n2.shtml

相关文章

Python 爬虫之微信公众号

Python 爬虫之微信公众号 源代码放在文末。 本次爬虫需要的工具如下: selenium 驱动器对应浏览器的 webdriver一个微信订阅号在 2017 年 6 月左右,微信官方发布一篇文章 https://mp.weixin.qq.com/s/67sk-uKz9Ct4niT-f4u1KA,大致意思就是以后发布文章的时候可以插入其他公…

公网访问局域网家用nas

提到外网访问不得不说说家里局域网的搭建结构了&#xff0c;就拿大众最常用的方式举例&#xff0c;网络运营商的光纤入户&#xff0c;通过运营商提供的光猫直接pppoe进行拨号&#xff0c;再连接自己的路由器&#xff0c;分配至各网口。 自从上次充当灵魂画手被嘲笑了以后就改用…

外网访问群晖NAS VMM搭建Openwrt的admin界面

偶然在网上看到很多的帖子使用群晖搭建openwrt搭建旁路由,心血来潮体验了一把,记录一下自己的搭建的整个过程,并最终实现外网访问Openwrt的admin界面。 本人使用的群晖nas DS220+,其他品牌未尝试。 一、前期配置 1、先在套件中心下载VMM(Virtaul Machine Manager) 2、下…

2022年10月 cpolar软件实现内网穿透连接群晖NAS

前言 1.cpolar简介 cpolar是一款拥有远程控制和内网穿透功能的软件。而且还可以监控端口的HTTP请求&#xff0c;利用实时的cpolar Web UI开发者工具&#xff0c;让您调试代码更容易。您可以监听所有隧道上的HTTP消息包&#xff0c;分析消息包的结构内容&#xff0c;找出问题点…

群晖内网穿透 实现外网快速访问 无需公网

有群晖的情况下&#xff0c;在内网我们可以通过ip正常访问我们的群晖/NAS;但是我们想要在外网访问的时候该怎么办&#xff0c;没有公网ip&#xff0c;扯专线太贵&#xff0c;自己搭建太麻烦。这无疑是个难题&#xff1b; 今天&#xff0c;小编找到了一款免费的内网穿透工具来实…

通过公网+域名访问家里的群晖服务器

公网域名访问群晖服务器 前言准备的东西如何判断你家里的宽带是公网IP通过公网IP网访群晖&#xff0c;端口映射申请域名和DDNS添加DDNS映射写在最后 前言 最近换了个工作&#xff0c;然后有代码的托管需求。想想用GitHub太卡了&#xff0c;国内的开源托管网站因为一些国人的素…

猫盘群晖外部网络访问的三种方法:公网IP、内网穿透、qc的实际评测

目录 具体过程概述内网穿透公网IPQuickconnect(QC&#xff09;结语 具体过程 概述 最近想入手一个NAS&#xff0c;由于我是新手入门&#xff0c;就选择入手了便宜的猫盘。我的猫盘是白群晖系统所以支持QC的功能&#xff0c;因此对目前猫盘群晖的DiskStation Manager&#xff…

特征值和特征矩阵

写一点对矩阵特征值和特征矩阵的理解 1. A是一个矩阵&#xff0c;它作用在向量v上。如果A是2阶对角阵的话&#xff0c;它起到的作用是将向量v在横纵方向拉伸 2. 当A是一个普通2阶矩阵时&#xff0c;它对v的拉伸不再是横纵方向&#xff0c;而是任意方向的&#xff0c;这取决于实…

三阶矩阵求特征值的快速算法

一般的三阶矩阵求特征值其实是解析不了的&#xff0c;因为特征方程对应的是三次方程&#xff0c;对于一般的三次方程&#xff0c;是很难求解的。要想方程有三个整数根&#xff0c;并且能够不用完全暴力展开三阶行列式这样的矩阵实际是很特殊的。 1.某一行有两个0的情况是最好算…

用R求矩阵的特征值和特征向量

最近在学习多元统计分析的主成分分析时&#xff0c;发现需要经常计算矩阵的特征值和特征向量&#xff0c;自己就找了下用R来做计算的函数。 我们可以用sigen()函数来计算特征对。 #创建一个矩阵 a <- matrix(c(11,sqrt(3)/2,3/2,sqrt(3)/2,21/4,5*sqrt(3)/4,3/2,5*sqrt(3)/…

怎么算特征值和特征矩阵?

怎样更通俗的理解特征值和特征矩阵&#xff1f; 设A是一个n阶矩阵&#xff0c;若数和n维非零列向量满足&#xff0c;数称为A的特征值&#xff0c;x称为A对应于特征值的特征向量。此时叫做特征多项式&#xff0c;若特征多项式为0则称为A的特征方程&#xff08;齐次线性方程组&a…

矩阵特征值和特征向量的求取

最近项目中有一个模块需要求矩阵的最大特征值和特征值对应的特征向量&#xff0c;无奈&#xff0c;又重新将以前学习的这方面的知识重新温习了一遍&#xff0c;感觉还是当时学的不够深&#xff0c;所以谢谢感悟&#xff0c;顺便对知识点进行一个总结。 首先特征值和特征向量的…

matlab如何求矩阵特征值

根据线性代数理论&#xff0c;特征值与特征向量只存在于方阵。如下所示为一方阵A&#xff1a; 在matlab输入矩阵&#xff1a; A [1 2 4; 4 0 7 9 1 3]; 查阅matlab help可以知道&#xff0c;利用eig函数可以快速求解矩阵的特征值与特征向量。 格式&#xff1a;[V,D] eig(A) 说…

delphi 连接轻量级数据库 sqlite3

环境: windows7-64, delphi7, sqlite3 最近搞个小工具&#xff0c;要用到轻量级数据库。以前小型数据库是用mdb的&#xff0c;但连接mdb 需要odbc的支持。 对环境依赖性很大&#xff0c;于是换了一种传说中的轻量级数据库。 sqlite 很小巧&#xff0c;delphi 7 连接sqlite…

轻量级数据库sqlite,spring boot+sqlite的配置详解 (一)

spring bootsqlite的配置&#xff0c;及成功运行详解 sqlite数据库的安装与调试 首先&#xff0c;通过sqlite官方地址下载对应的安装包 https://www.sqlite.org/download.html 下载对应版本的安装包和工具包 解压后会得到这几个文件&#xff0c;将这几个文件放在同一目录下 …

腾讯云——轻量数据库服务

轻量数据库服务采用腾讯云自研的新一代云原生数据TDSQL-C&#xff0c;融合了传统数据库、云计算与新硬件技术的优势&#xff0c;100%兼容 MySQL&#xff0c;实现超百万级 QPS 的高吞吐&#xff0c;128TB 海量分布式智能存储&#xff0c;保障数据安全可靠。 定制内核&#xff1…

轻量级关系数据库SQLite的安装和SpringBoot整合

简介 SQLite是轻量级的关系型数据库&#xff0c;适用于中小型应用场景&#xff1a;如安卓、网站、终端设备。并且轻量&#xff08;服务端1M&#xff09;、方便移植&#xff08;只需要移动*.db文件到另外一台电脑&#xff09; 安装 官网链接&#xff1a;https://www.sqlite.o…

HarmonyOS之数据管理·轻量级偏好数据库的应用

一、简介 ① 基本概念 轻量级偏好数据库主要提供轻量级 Key-Value 操作&#xff0c;支持本地应用存储少量数据&#xff0c;数据存储在本地文件中&#xff0c;同时也加载在内存中的&#xff0c;所以访问速度更快&#xff0c;效率更高。轻量级偏好数据库属于非关系型数据库&…

使用 C# 开发的轻量级开源数据库 LiteDB

你好&#xff0c;这里是 Dotnet 工具箱&#xff0c;定期分享 Dotnet 有趣&#xff0c;实用的工具或组件&#xff0c;希望对您有用&#xff01; 简介 LiteDB 是一个小型、快速、轻量级的 .NET NoSQL 嵌入式数据库&#xff0c;也就是我们常说的 K/V 数据库&#xff0c;完全用 C…

开源轻量级数据库访问框架

本框架为开源框架&#xff0c;旨在简化用户的数据库操作&#xff0c;提供便捷的数据库访问服务而封装。该框架依赖于JDBC&#xff0c;并且基于原生JAVA SE框架的封装。 框架对比 对于经常进行数据库开发和JAVA EE开发的编程人员而言&#xff0c;其最先使用到的数据持久化方式…