微信公众号后台编辑素材界面的原理和原理
优采云 发布时间: 2021-07-26 22:05微信公众号后台编辑素材界面的原理和原理
准备阶段
为了实现这个爬虫,我们需要使用以下工具
另外,这个爬虫程序使用了微信公众号后台编辑素材接口。原理是当我们插入超链接时,微信会调用一个特殊的API(见下图)来获取指定公众号的文章列表。因此,我们还需要有一个官方帐号。
fig1 正式启动
我们需要登录微信公众号,点击素材管理,点击新建图文消息,然后点击上面的超链接。
图2
接下来,按 F12,打开 Chrome 的开发者工具,然后选择网络
图3
此时,在之前的超链接界面,点击“选择其他公众号”,输入你需要抓取的公众号(例如中国移动)
图4
这时候之前的Network会刷新一些链接,其中“appmsg”开头的内容就是我们需要分析的
图5
我们解析请求的 URL
https://mp.weixin.qq.com/cgi-bin/appmsg?action=list_ex&begin=0&count=5&fakeid=MzI1MjU5MjMzNA==&type=9&query=&token=143406284&lang=zh_CN&f=json&ajax=1
分为三个部分
通过不断浏览下一页,我们发现每次只有begin会改变,每次增加5,这就是count的值。
接下来我们使用Python获取同样的资源,但是直接运行下面的代码是无法获取资源的。
import requestsurl = "https://mp.weixin.qq.com/cgi-bin/appmsg?action=list_ex&begin=0&count=5&fakeid=MzI1MjU5MjMzNA==&type=9&query=&token=1957521839&lang=zh_CN&f=json&ajax=1"requests.get(url).json() # {'base_resp': {'ret': 200003, 'err_msg': 'invalid session'}}
之所以能在浏览器上获取资源,是因为我们登录了微信公众号后台。而Python没有我们的登录信息,所以请求无效。我们需要在requests中设置headers参数,并传入Cookie和User-Agent来模拟登录
由于头信息的内容每次都会变化,所以我把这些内容放在一个单独的文件中,即“wechat.yaml”,信息如下
cookie: ua_id=wuzWM9FKE14...user_agent: Mozilla/5.0...
你只需要稍后阅读
# 读取cookie和user_agentimport yamlwith open("wechat.yaml", "r") as file: file_data = file.read()config = yaml.safe_load(file_data)headers = { "Cookie": config['cookie'], "User-Agent": config['user_agent'] }requests.get(url, headers=headers, verify=False).json()
在返回的JSON中,我们可以看到每个文章的标题(title)、摘要(digest)、链接(link)、推送时间(update_time)和封面地址(cover)。
❝
appmsgid 是每条推文的唯一标识符,aid 是每条推文的唯一标识符。
❞
图 6 ❝
其实除了cookies,URL中的token参数也会用来限制爬虫,所以上面代码的输出很可能是{'base_resp': {'ret': 200040,'err_msg ':'无效的 csrf 令牌'}}
❞
接下来,我们编写一个循环来获取所有文章 JSON 并保存。
import jsonimport requestsimport timeimport randomimport yamlwith open("wechat.yaml", "r") as file: file_data = file.read()config = yaml.safe_load(file_data)headers = { "Cookie": config['cookie'], "User-Agent": config['user_agent'] }# 请求参数url = "https://mp.weixin.qq.com/cgi-bin/appmsg"begin = "0"params = { "action": "list_ex", "begin": begin, "count": "5", "fakeid": config['fakeid'], "type": "9", "token": config['token'], "lang": "zh_CN", "f": "json", "ajax": "1"}# 存放结果app_msg_list = []# 在不知道公众号有多少文章的情况下,使用while语句# 也方便重新运行时设置页数i = 0while True: begin = i * 5 params["begin"] = str(begin) # 随机暂停几秒,避免过快的请求导致过快的被查到 time.sleep(random.randint(1,10)) resp = requests.get(url, headers=headers, params = params, verify=False) # 微信流量控制, 退出 if resp.json()['base_resp']['ret'] == 200013: print("frequencey control, stop at {}".format(str(begin))) break # 如果返回的内容中为空则结束 if len(resp.json()['app_msg_list']) == 0: print("all ariticle parsed") break app_msg_list.append(resp.json()) # 翻页 i += 1
在上面的代码中,我还在“wechat.yaml”文件中存储了fakeid和token。这是因为 fakeid 是每个公众号的唯一标识符,令牌会经常变化。这个信息可以通过解析URL获取,也可以在开发者工具中查看
图7
爬取一段时间后,会遇到以下问题
{'base_resp': {'err_msg': 'freq control', 'ret': 200013}}
此时在公众号后台尝试插入超链接时,会遇到如下提示
图8
这是公众号的流量限制,通常需要等待30-60分钟才能继续。为了完美处理这个问题,你可能需要申请多个公众号,可能需要对抗微信公众号登录系统,或者你可能需要设置代理池。
但是我不需要工业级的爬虫,我只想爬取自己的公众号信息,所以等了一个小时,再次登录公众号,获取cookie和token,运行。我不想用自己的兴趣挑战别人的工作。
最后,将结果保存为 JSON 格式。
# 保存结果为JSONjson_name = "mp_data_{}.json".format(str(begin))with open(json_name, "w") as file: file.write(json.dumps(app_msg_list, indent=2, ensure_ascii=False))
或者提取文章identifier、标题、网址、发布时间四列,保存为CSV。
info_list = []for msg in app_msg_list: if "app_msg_list" in msg: for item in msg["app_msg_list"]: info = '"{}","{}","{}","{}"'.format(str(item["aid"]), item['title'], item['link'], str(item['create_time'])) info_list.append(info)# save as csvwith open("app_msg_list.csv", "w") as file: file.writelines("\n".join(info_list))