推荐文章:Python+fiddler:爬取微信公众号的文章

优采云 发布时间: 2022-10-20 10:25

  推荐文章:Python+fiddler:爬取微信公众号的文章

  这几天,师父有一个小项目,很有意思。如何使用python抓取微信公众号中的新闻信息。一般流程如下。

  图 1:流程

  其实我们可以看到这里并没有想象中的“智能”——还是需要手动刷公众号文章,然后才能采集信息。(错误:更新的第 9 部分更智能,更少手动滑动)

  1.从你的电脑下载fiddler

  图 2:下载 fiddler2。安装后,首先看到的是这个

  图 3:第一次打开 fiddler 后

  这里是fiddler的介绍。

  3.设置

  图4:设置工具-选项-HTTPS

  然后设置操作:单击操作,选择信任根证书并将根证书导出到桌面(出现提示时选择是)。

  图 5:设置操作

  图 6:设置工具-选项-连接4。手机设置(我用的是红米手机,其他手机大致相同)

  图 7:设置移动 WiFi 代理(代理)

  图8:手机进入网站192.168.124.14:8888

  图 9:点击 FiddlerRoot 证书

  图10:下载后安装,随便起个名字,我命名为“Fiddler2”

  5.重启电脑Fiddler,手机打开公众号文章,电脑Fiddler采集信息

  图 11:录制

  图 12:详细分析

  图13:复制Fiddler记录的链接,在浏览器中点击

  图 14:过滤

  图 15:过滤后的信息

  可以看出,由于过滤起到了作用,所以序列号出现了跳跃。

  6.导出所有信息

  图 16:导出移动浏览历史

  图 17:txt 信息 7. Python 提取公众号信息

  import numpy as np

data = []

with open(r'...\1_Full.txt', 'r', encoding='utf-8') as fp:

for line in fp:

if 'Referer: https://mp.weixin.qq.com/' in line: //将含有重要信息的链接保留到data中

data.append(line[9:])

// 去重

data = np.unique(data)

  8.通过电脑微信客户端抓取公众号信息

  一遍遍地刷手机后,我一定很无聊。. 如果你可以通过鼠标点击电脑作为内部客户端,然后通过fiddler采集信息,那么你就不需要刷手机了。. 注意调整fiddler的时候,anaconda的jupyter是关闭的(spyder可以用),否则fiddler会有问题。

  操作几乎相同。

  首先,修改fiddler-Tools-Options-HTTPS,将HTTPS流量解密为“来自所有进程”。

  图18:电脑采集微信公众号的操作

  然后,同样在自己的浏览器中,输入IP地址+8888下载证书。

  图 19:下载 FiddlerRoot 证书

  下载后安装。

  图 20:安装证书

  过滤器的其他设置和上面的手机设置一样,都是过滤掉关于wp.weixin的内容。

  然后,在电脑上刷一下微信公众号,过滤器就可以记录所有公众号文章。注意一旦开启fiddler,电脑无法访问其他网页,因为百度等反爬机制非常严格,会检测到fiddler已经启动。

  9. 操作更自动化、智能化

  无论是刷手机采集信息,还是通过电脑刷公众号,仍然需要人点击信息,不够智能。参考新案例后,这里可以进行颠覆性的改进。

  首先,本文前面的模块仍然需要了解。当你已经可以在电脑端刷微信公众号文章,fiddler可以采集https信息,然后继续下一步。以微信公众号“首都之窗”为例。

  (一)电脑微信端操作

  打开提琴手。

  点击设置-通用设置-使用系统默认浏览器打开网页。

  图 21:电脑微信设置

  然后,随意点击“资本窗口”的任意文章,就会在浏览器中弹出。把它放在那里并忽略它。顺便把fiddler中记录的文章信息删除了。把提琴手留空,记录下图25的关键内容!

  这一步的目的是为了在浏览器中顺利打开和刷新公众号的历史新闻。

  图 22:首先单击 文章

  图 23:文章 在浏览器中弹出

  图 24:完成操作

  然后,进入“首都之窗”公众号,点击查看历史新闻。

  图 25:查看历史消息

  同理,浏览器弹出“历史消息”(微信客户端不能下拉,因为fiddler收不到信息),然后开始往下滑几下,需要看到新的内容弹出,同时您看到 fiddler 正在记录更新的信息。fiddler 更新消息是最重要的内容。

  图 26:在浏览器中多次下拉“历史消息”

  (2)提琴手信息分析

  只需在浏览器中下拉公众号历史消息,fiddler采集就得到了更新的信息。让我们开始分析。

  图 27:分析由于下拉历史消息而采集的记录

  选择第8条记录(这条记录来自浏览器下拉历史采集到的消息),重要的部分已经圈在了表头。

  (3)链接分析(看不懂就看代码怎么拼出链接的)

  首先,在Request headers中,该链接全拼是/mp/profile_ext?action=getmsg&__biz=MzA5NDY5MzUzMQ==&f=json&offset=20&count=10&is_ok=1&scene=124&uin=777&key=777&pass_ticket=&wxtoken=&appmsg_token=1052_D6g2L7mM%252BaKLoVQK33V8q4D4wk3doi7QeR3Zog~~&x5 =0&f=json HTTP/1.1

  

  分析这个链接。如您所见,它由几个部分组成。

  ①/mp/profile_ext? ②action=getmsg ③&__biz=MzA5NDY5MzUzMQ== ④&f=json⑤&offset=20 ⑥&count=10 ⑦&is_ok=1 ⑧&scene=124 ⑨&uin=777 ⑩&key=777 ⑪&pass_ticket= ⑫&wxtoken= ⑬&appmsg_token=1052_D6g2L7mM%252BaKLoVQK33V8q4D4wk3doi7QeR3Zog~~ ⑭&x5=0&f=json HTTP/1.1

  那么我们需要注意的信息是:

  ③__biz:公众号的id(公众号的biz是唯一的),⑤offset:翻页标志,⑬appmsg_token:时间敏感的token(一段时间后会改变)

  让我们看看以下链接

  GET /mp/profile_ext?action=getmsg&__biz=MzA5NDY5MzUzMQ==&f=json&offset=40&count=10&is_ok=1&scene=124&uin=777&key=777&pass_ticket=&wxtoken=&appmsg_token=1052_D6g2L7mM%252BaKLoVQK33V8q4D4wk3doi7QeR3Zog~~&x5=0&f=json HTTP/1.1

  GET /mp/profile_ext?action=getmsg&__biz=MzA5NDY5MzUzMQ==&f=json&offset=60&count=10&is_ok=1&scene=124&uin=777&key=777&pass_ticket=&wxtoken=&appmsg_token=1052_D6g2L7mM%252BaKLoVQK33V8q4D4wk3doi7QeR3Zog~~&x5=0&f=json HTTP/1.1

  biz 和 appmsg_token 一样,改变了偏移量,是一个新的页面。因此,在第一步中,我们找到了翻页的规律。只有这三个在链接中发生变化,其他不变。因此,该链接可以用 python 编写为:

  api = 'https://mp.weixin.qq.com/mp/profile_ext?action=getmsg&__biz={0}&f=json&offset={1}&count=10&is_ok=1&scene=124&uin=777&key=777&pass_ticket=&wxton=&appmsg_token={2}&x5=0&f=json HTTP/1.1'.format(

__biz, offset, appmsg_token)

  (4) cookie 和标头

  cookie保存微信登录信息,抓取时需要填写。我们只需要关注wsp_sid2的cookies信息即可。

  cookie 也来自图 27。发现 wap_sid2=CK6vyK4CElxLdmda............

  标题也来自图 27。找到“User-Agent”:“Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362”

  (5) 爬行

  好了,上面找到了很多资料。初始python如下:

  import requests

import json

# 链接拼接三个信息

__biz = "MzA5NDY5MzUzMQ=="

appmsg_token = "1052_D6g2L7mM%252BaKLoVQK33V8q4D4wk3doi7QeR3Zog~~"

offset = 20

# cookies和headers

cookies = "wap_sid2=CK6vyK4CElxLdmda......."

headers = {'Cookie':cookies,

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362"

}

# api拼出来

api = 'https://mp.weixin.qq.com/mp/profile_ext?action=getmsg&__biz={0}&f=json&offset={1}&count=10&is_ok=1&scene=124&uin=777&key=777&pass_ticket=&wxton=&appmsg_token={2}&x5=0&f=json HTTP/1.1'.format(

__biz, offset, appmsg_token)

# 抓取并且json化

resp = requests.get(api, headers = headers, verify=False).json()

  为什么你需要jsonize resp?我们可以尝试打开9(3)开头链接的网页,

  图28:拼写api打开的网页是这样的

  显然这是一条 json 消息。因此需要json化。把网页的整个文本复制下来放到网页里面,就可以看到完整的json结构了。这是 resp 的 web 结果。

  图 29:将图 28 的文本信息复制到

  那么resp在python中json化后的结果如下

  图30:python中resp的结构

  (6) 网页分析

  接下来重点介绍resp的结构和逐层分析。图30中,resp中的errmsg=ok和ret=0,都表示网页可以正常打开(如果报错,ret=-3)。next_offset 为下一页的翻页标志,需要保存。

  next_offset = resp.get('next_offset')

general_msg_list = resp.get('general_msg_list')

# 将general_msg_list转为json格式

msg_list = json.loads(general_msg_list)['list']

  general_msg_list 是重要内容。点击general_msg_list,依然是json结构。

  图 31:general_msg_list 仍然是一个 json 结构。

  把里面的文字复制出来放在中间看看是什么。

  图 32:将 general_msg_list 放入的结果

  所以被json化后的msg_list在python中是这样的

  图 33:在 python 中 jsonizing general_msg_list

  可以看到,msg_list 中有 10 条记录。我们抽出一条记录进行具体分析。在分析之前,我们需要明确一件事。msg_list 收录 10 条记录,不是 10 条 文章,而是 10 条推送。某个公众号推送消息可能同时发布多个文章,也可能是一个文章。因此,请了解单个 msg 记录是指推送(可能同时有多个 文章)。

  图 34:一次推送 3 篇文章一起发表 文章

  msg = msg_list[0]

  图 35:特定消息

  味精收录“app_msg_ext_info”和“comm_msg_info”。在 中,两个内容是这样的。

  图 36:msg 的两个特定部分---app_msg_ext_info 和 comm_msg_info

  然后comm_msg_info收录了推送的基本信息:推送ID、时间等。

  什么是 app_msg_ext_info?让我慢慢分析。首先title、digest一路到is_multi,都是push的开头文章(也就是图34中图片的文章的信息)。比如titletitle/digest关键词/content_url链接/source_url原创链接等。

  is_multi 是判断push是否有读文章;=1 表示是,=0 表示否。那么这个等于1,说明本次推送中还有其他的文章,存在于multi_app_msg_item_list中。

  取出 multi_app_msg_item_list。

  multi_app_msg_item_list = app_msg_ext_info.get('multi_app_msg_item_list')

  图 37:推送 文章 的剩余两篇文章隐藏在 multi_app_msg_item_list

  至此,我们已经分析了整个流程。

  总结

  图 38:总结如何迈出第一步

  图 39:详细的分析结构

  (7)具体代码如下

  import requests

import json

from datetime import datetime

import pandas as pd

import time

class WxMps:

def __init__(self, biz, appmsg_token, cookies, offset, city):

self.biz = biz

self.msg_token = appmsg_token

self.offset = offset

<p>

self.headers = {&#39;Cookie&#39;:cookies, &#39;User-Agent&#39;: &#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36&#39;

}

self.city = city

def parse1(self, resp):

# 控制下一个抓取的offset

offset = resp.get(&#39;next_offset&#39;)

# 将包含主要内容的list转为json格式

general_msg_list = resp.get(&#39;general_msg_list&#39;)

# 一个msg_list中含有10个msg

msg_list = json.loads(general_msg_list)[&#39;list&#39;]

df1 = pd.DataFrame(columns = [&#39;msg_id&#39;, &#39;post_time&#39;, &#39;msg_type&#39;, &#39;title&#39;, &#39;cover&#39;, &#39;author&#39;, &#39;digest&#39;, &#39;source_url&#39;, &#39;content_url&#39;])

# 循环message列表

for msg in msg_list:

# msg是该推送的信息,包含了comm_msg_info以及app_msg_ext_info两个信息,注意某一个推送中可能含有多个文章。

comm_msg_info = msg.get(&#39;comm_msg_info&#39;)

app_msg_ext_info = msg.get(&#39;app_msg_ext_info&#39;)

# 该推送的id

msg_id = comm_msg_info.get(&#39;id&#39;)

# 该推送的发布时间,例如1579965567需要转化为datetime,datetime.fromtimestamp(1579965567)

post_time = datetime.fromtimestamp(comm_msg_info[&#39;datetime&#39;])

# 该推送的类型

msg_type = comm_msg_info.get(&#39;type&#39;)

if app_msg_ext_info:

# 推送的第一篇文章

title, cover, author, digest, source_url, content_url = self.parse2(app_msg_ext_info)

df2 = self.df_process(msg_id, post_time, msg_type, title, cover, author, digest, source_url, content_url)

df1 = pd.concat([df1, df2])

# 判断是不是多篇文章

is_multi = app_msg_ext_info.get("is_multi")

# 如果是1,继续爬取;如果是0,单条推送=只有一篇文章

if is_multi:

multi_app_msg_item_list = app_msg_ext_info.get(&#39;multi_app_msg_item_list&#39;)

for information in multi_app_msg_item_list:

(title, cover, author, digest, source_url, content_url) = self.parse2(information)

df2 = self.df_process(msg_id, post_time, msg_type, title, cover, author, digest, source_url, content_url)

df1 = pd.concat([df1, df2])

return df1, offset

def start(self):

offset = self.offset

df1 = pd.DataFrame(columns = [&#39;msg_id&#39;, &#39;post_time&#39;, &#39;msg_type&#39;, &#39;title&#39;, &#39;cover&#39;, &#39;author&#39;, &#39;digest&#39;, &#39;source_url&#39;, &#39;content_url&#39;])

while offset

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线