前言

微信后台很多消息未回复:看到时已经回复不了。有问题可以添加我的微信:菜单 ->联系我 

由于最近需要公众号的历史文章信息,所以就尝试爬了一下,虽然目前可以爬到数据,但是还不能够大量的自动化爬取。原因是参数key值具有时效性(具体时间没有验证20分钟的样子),目前也不知道是如何生成的。

文章历史列表爬取

首先先到的是搜狗微信,但是搜狗微信只能看到前十篇文章并且查不到阅读量和在看的数量,尝试爬取手机包,发现没有抓取到信息,后来才知道原因:

1、安卓系统7.0以下,微信信任系统的证书。

2、安卓系统7.0以上,微信7.0一下版本,微信信任系统提供的证书。

3、安卓系统7.0以上,微信7.0以上版本,微信只信任自己的证书。

也尝试过使用appium自动化爬取,个人觉得有点麻烦。所以就尝试抓取PC端的请求。

进入正题,这次抓包使用的是Fiddler。下载链接:https://www.telerik.com/fiddler

Fiddler如何抓包这里不再一一阐述,首先第一次安装Fiddler是需要安装证书才可以抓取HTTPS请求的,

如何安装?

打开Fiddler,从菜单栏找到Tools -> Options -> 点击HTTPS -> 点击Actions 会安装证书 配置成如下:

这里以我自己的公众号为例:在PC端登陆微信,打开Fiddler,按F12是开启/停止抓包,进入公众号历史文章页面,看到Fiddler出现了很多请求,如下图:

由于查看历史记录是跳转到一个新的页面,可以从Body返回较多的看起,同时通过Content-Type也可以知道返回的是css或者html或者js,可以先从html看,于是乎就会找到如上图红色框中的链接,点击他,可以从右边看到返回结果和参数:

从右边的Headers中可以看到请求的链接,方式,参数等,如果想要更清晰的查看参数可以点击WebForms查看,也就是上图展示的结果。这里来描述一下其中重要的参数:

__biz:微信公众号的唯一标识(同一公众号不变)

uin:用户唯一标识(同一个微信用户不变)

key:微信内部算法,具有时效性,目前不知道是如何算出来的。

pass_ticket:是有一个阅读的权限加密,是变化的(在我实际的爬取中发现是不需要的,可以忽略不计)

走到这一步其实已经可以写代码爬取第一页的文章了,但是返回的是html页面,解析页面明显是比较麻烦的。

可以尝试往下滑动,加载下一页数据,看看返回的是json还是html,如果是json就好办,如果还是html,那就只好一点点的解析了。继续往下走会发现:

这个请求就是返回的文章列表,并且是json数据,这就很方便我们去解析了,从参数中发现有一个参数为offset为10,很明显这个参数就是分页的偏移量,这个请求为10加载的是第二页的历史记录,果断修改成0,再发送请求,得到的就是第一页的数据,那么就不需要再去解析html页面了,再次分析参数,发现看着看多参数,有很多一部分是没有用的,最终需要的参数有:

action:getmsg(固定值,应该表示获取更多信息吧)

__biz,uin,key这三个值在上面已经描述了,在这里也是必须的参数

f:json(定值,表示返回json数据吧)

offset:分页偏移量

想要获取公众号的历史列表,这6个参数是必须的,其他的参数可以不用带上。再来分析请求头中的hearders如图:

参数很多,我也不知道那些该带,那些不需要带,最后发现只需要携带UA就可以了,其他都可以不要。最终写出脚本来尝试获取一下:

import requests
url = "链接:http://链接:mp.weixin链接:.qq.com/mp/profile_ext"
headers= {'User-Agent':'Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Mobile/14A403 MicroMessenger/6.5.18 NetType/WIFI Language/zh_CN'
}
param = {'action': 'getmsg','__biz': 'MzU0NDg3NDg0Ng==','f': 'json','offset': 0,'uin': 'MTY5OTE4Mzc5Nw==','key': '0295ce962daa06881b1fbddd606f47252d0273a7280069e55e1daa347620284614629cd08ef0413941d46dc737cf866bc3ed3012ec202ffa9379c2538035a662e9ffa3f84852a0299a6590811b17de96'
}index_josn = requests.get(url, params=param, headers=headers)
print(index_josn.json())
print(index_josn.json().get('general_msg_list'))

获取json对象中的general_msg_list,得到的结果:

获取文章详情

上面已经拿到了链接,请求解析html页面就可以了。这里不再阐述(在全部代码中可以查看)。

获取阅读量和再看量

抓包方式等上面已经说了,在这里就不再废话了

点进文章,滑动到最下方(在快到达底部的时候才会去请求阅读量和再看量),很容易就会捕捉到的请求:

获取阅读量和在看量:

/mp/getappmsgext?f=json&mock=&uin=...(太长了)

获取评论:

/mp.weixin.qq.com/mp/appmsg_comment...

这里我只获取了阅读量和在看量(评论没有去获取但是都是一样的)查看需要的参数:

分析这个请求的参数(这个请求参数真的太多了,心中mmp)发现:

url需要参数:在url中只需要携带uin(用户id)和key值

hearders需要参数:至需要UA

body需要参数:

__biz:公众号唯一标识

appmsg_type:9 (目前来看都是9,必须携带)

mid和sn必须携带,更具这两个参数来判断是那篇文章。

inx:文章的排序,必须携带,对应错获取不到。

is_only_read:1(目前来看都是1,必须携带)

获取阅读量和再看量的代码为:

import requests# 查询评论接口  重要参数:uin :微信用户唯一ID   key:具有失效性的key
url = '链接:https://链接:mp.weixin链接:.qq.com/mp/getappmsgext?uin={你的uin}&key={你的key}
hearder = {'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D57 MicroMessenger/7.0.3(0x17000321) NetType/WIFI Language/zh_CN',
}# body参数重要参数:__biz: 微信公众号唯一ID   appmsg_type:定值, 必须有
# mid 和 sn 变化值 从上一个页面可以获取       inx 定值  is_only_read 定值
data = {'__biz': 'MzIwMjM5ODY4Mw==',  # 公众号唯一ID  必须'appmsg_type': '9',  # 和 在看 有关 必须'mid': '2247500578',  # 必须   # 不同文章 不同'sn': 'bcfbfe204ac8d6fb561c6a8e330f4c55',  # 必须 和文章有关'idx': '1',  # 必须'is_only_read': 1,  # 必须 和阅读,在看有关
}index = requests.post(url, headers=hearder, data=data)
print('结果')
print(index.json())
print('在看')
print(index.json().get('appmsgstat').get('like_num'))
print('浏览')
print(index.json().get('appmsgstat').get('read_num'))

最终整理脚本如下

import requests
import json
from urllib import parse
import re
from lxml import etree
import html
import timeheaders = {'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Mobile/14A403 MicroMessenger/6.5.18 NetType/WIFI Language/zh_CN'
}articles_url = "链接http:链接//mp.weixin.qq.com链接/mp/profile_ext"
yuedu_url = '链接https:链接//mp.weixin.qq.com/mp链接/getappmsgext'
y_param = {}
param = {'action': 'getmsg','__biz': 'MzIyNTY4MDcxNA==','f': 'json','offset': 0,'uin': 'MTY5OTE4Mzc5Nw==','key': 'c072b2c2faef4d94fcb6bd27030bdbbb60fc420b14aad30b763f17d4b0e872c5b68bd45fd7392cb9c554e236d16b84310e7ff377e5b3dbdc5732cd8346ea721a3d1c6ef7dc2f2ac0106ac04a6b540948'
}
data = {'is_only_read': '1','appmsg_type': '9'
}is_bottom = Falsedef get_articles_list():'''获取文章列表:return: 返回文章列表 list'''articles_json = requests.get(articles_url, params=param, headers=headers).json()if 'base_resp' in articles_json.keys():print('key值可能失效')return Nonereturn articles_jsondef analysis_articles_list():'''解析文章列表参数获取除 文章,点赞,在看的所有信息:return: 一个字典'''# 获取 10 篇articles_json = get_articles_list()articles_info = {}# 不为空  获取当前文章数 等于0表示没有了if articles_json and articles_json.get('msg_count') > 0:# 获取文章列表articles_lsit = json.loads(articles_json.get('general_msg_list'))if articles_lsit.get('list'):for articles in articles_lsit.get('list'):articles_info['datetime'] = articles.get('comm_msg_info').get('datetime')if articles.get('app_msg_ext_info'):articles_info = dict(articles_info, **articles.get('app_msg_ext_info'))articles_info['is_Headlines'] = 1yield articles_infoif articles_info.get('is_multi'):for item in articles_info.get('multi_app_msg_item_list'):articles_info = dict(articles_info, **item)articles_info['is_Headlines'] = 0yield articles_infoelse:global is_bottomis_bottom = Truedef get_articles_digset(articles_info):time.sleep(5)content_url = articles_info.get('content_url').replace('amp;', '')cansu = parse.parse_qs(parse.urlparse(content_url).query)html_text = requests.get(content_url, headers=headers).texthtml_text = etree.HTML(html_text)html_text = html_text.xpath('//div[@id="js_content"]')[0]html_text = etree.tostring(html_text).decode('utf-8')dr = re.compile(r'<[^>]+>', re.S)wenzhang_text = dr.sub('', str(html_text))articles_info['text'] = html.unescape(wenzhang_text).strip()y_param['uin'] = param['uin']y_param['key'] = param['key']data['__biz'] = param['__biz']data['mid'] = cansu['mid'][0]data['sn'] = cansu['sn'][0]data['idx'] = cansu['idx'][0]y_json = requests.post(yuedu_url, headers=headers, params=y_param, data=data).json()try:articles_info['read_num'] = y_json.get('appmsgstat').get('read_num', '0')articles_info['like_num'] = y_json.get('appmsgstat').get('like_num', '0')except Exception as e:articles_info['read_num'] = 0articles_info['like_num'] = 0print(e)return articles_infodef insert_data(all_data):print(all_data)def get_dime(timestamp):# 利用localtime()函数将时间戳转化成时间数组localtime = time.localtime(timestamp)dt = time.strftime('%Y-%m-%d %H:%M:%S', localtime)return dtdef main():# 主入口for offset in range(1, 1000):# 分页获取文章列表if not is_bottom:print('正在爬取第%d页' % offset)if offset % 2 == 0:time.sleep(5)param['offset'] = (offset-1) * 10for articles in analysis_articles_list():articles_info = get_articles_digset(articles)insert_data(articles_info)else:breakif __name__ == "__main__":main()

还存在的问题

参数uin:用户的唯一id,是不用改变的,问题不大

参数__biz:可以通过搜狗微信获取(通过搜狗微信搜索公众号可以在页面找到__biz)

参数key:问题很大,暂时没办法获取到

但是单独爬取一个公众号(文章不是特别多的时候)时间是够的。我在爬取的途中遇见了443的问题,可能是爬取太快,不知道加上代理ip有没有用(还没有尝试)

既然key要手动修改上去,我就索性没有去搜狗获取__biz。(有兴趣的可以去尝试一下)

key过期怎么办?

用Fiddler从新抓包获取新的key值,替换上去就可以了。

上面的源码复制下来需要把uin,__biz,key值换成自己的,url中由于微信限制,我添加了链接两个字,去掉就好了。

福利

最后送给大家一套爬虫视频:

后台回复爬虫视频获取。

下面这本书目前电子版只有第二版本,也放在上面的云盘中了。Python必看的书之一。

基于PC端的爬取公众号历史文章相关推荐

  1. python爬取公众号历史文章

    文章来源 学习网上以及自己修改. 参考链接: https://blog.csdn.net/d1240673769/article/details/75907152 目的 ''' 爬取公众号的历史文章信 ...

  2. python爬取公众号历史文章_pythons爬虫:抓取微信公众号 历史文章(selenium+phantomjs)...

    原标题:pythons爬虫:抓取微信公众号 历史文章(selenium+phantomjs) 大数据挖掘DT数据分析 公众号: datadw 本文爬虫代码可以通过回复本公众号关键字"公众号& ...

  3. python爬取公众号历史文章_Python爬虫爬取微信公众号历史文章全部链接

    因为朋友问我能不能找一下一个微信公众号的全部历史文章的链接,我就帮他弄了一下,通过百度和谷歌发现现在大家爬微信公众号的思路基本都是下面两种: 通过搜狗搜索微信公众号然后拿到链接 通过fiddler检测 ...

  4. python爬取公众号历史文章_python3 scrapy爬取微信公众号及历史信息V1.0

    妹子图.png 环境:python3  scrapy 目的 写这篇文章主要是做一下纪念,毕竟是搞了快两天的东西了,今天加大了量,使用scrapy爬取100多个微信公众号,然后出现IP被封的情况下,当然 ...

  5. python爬取公众号历史文章_python爬微信公众号前10篇历史文章(6)-话说http cookies...

    早期Web开发面临的最大问题之一是如何管理状态.简言之,服务器端没有办法知道两个请求是否来自于同一个浏览器.这是cookies的起源. 什么是cookie? A cookie is a small s ...

  6. Selenium自动化|爬取公众号全部文章,就是这么简单

    大家好,今天我们来讲点Selenium自动化,你是否有特别喜欢的公众号?你有思考过如何将一个公众号历史文章全部文章爬下来学习吗?现在我们以早起Python为例,使用Selenium来实现 下面就来详细 ...

  7. 爬取公众号全部文章,就是这么简单 |Selenium自动化

    Selenium介绍 Selenium 是一个用于web应用程序 自动化测试 的工具,直接运行在浏览器当中,可以通过代码控制与页面上元素进行交互,并获取对应的信息.Selenium 很大的一个优点是: ...

  8. 爬取公众号的文章,同时处理图片不显示问题(JAVA)

    Java代码下载(IDEA) Maven引入 <dependency> <groupId>org.apache.httpcomponents</groupId> & ...

  9. Python从放弃到入门,公众号历史文章爬取成pdf的项目实践与自主学习法

    这篇文章不谈江流所专研的营销与运营,而聊一聊技能学习之路,聊一聊Python这门最简单的编程语言该如何学习,我完成的第一个Python项目,将任意公众号的所有历史文章导出成PDF电子书. 或许我这个P ...

  10. python公众号推荐 知乎_爬取公众号及知乎专栏文章的标题链接的方法汇总

    记一次最近的工作内容(奇怪的任务增加了)因为Python是去年接触并且没有过爬虫的实际学习操作,所以在出现"要收集文章标题链接"的任务是还是有点难以下手的.虽然有了解过爬虫可以方便 ...

最新文章

  1. 事物的级别_浅谈MySQL并发控制:隔离级别、锁与MVCC
  2. iOS7系统iLEX RAT冬青鼠安装教程:无需刷机还原纯净越狱系统
  3. 运算符 - PHP手册笔记
  4. kpc v0.8.3发布,跨框架的组件库解决方案
  5. ***惯用的社会工程学手法
  6. IDEA HTTP状态 404 - 未找到 请求的资源[/]不可用
  7. step by step approach for building interactive dash app using python: step 1
  8. C++加号运算符重载
  9. Windows下Redis安装的那些事儿!
  10. Bailian2734 十进制到八进制【入门】(POJ NOI0113-45)
  11. Android------Button 添加声音效果(两种方式)
  12. Ubuntu系统上的ImageJ安装和卸载方法
  13. 计算机号密码保护,如何使用BIOS或UEFI密码保护计算机 | MOS86
  14. 传统车道线检测之黄白线、虚实车道线检测(附python代码)
  15. ping结果中TTL是什么意思
  16. linux必会的30道shell编程面试题及讲解
  17. JQuery解析二维码
  18. HTML标签关系——双标签和单标签,标签的嵌套与并列
  19. Vue-Waterfall-Easy插件详细使用教程
  20. oracle导出dmp文件

热门文章

  1. ios vue 添加本地音乐_vue怎么添加自己的音乐
  2. 最近在校园内发现暴风一号病毒(俗称1kb病毒),普及一下查杀和修复的方法
  3. yafu 下载_YAFUD
  4. Ubuntu下完全删除Edraw软件
  5. 软考初级信息处理技术员(一)
  6. java http proxy server
  7. ubuntu 安装mono Fiddler后The proxy server is refusing connections
  8. nginx启动报错:Failed to start The nginx HTTP and reverse proxy server.
  9. jsp九大内置对象的使用详解
  10. 二叉树遍历之层次遍历算法入门详解