Python 爬虫之微信公众号

Python 爬虫之微信公众号

源代码放在文末。

本次爬虫需要的工具如下:

在 2017 年 6 月左右,微信官方发布一篇文章 https://mp.weixin.qq.com/s/67sk-uKz9Ct4niT-f4u1KA,大致意思就是以后发布文章的时候可以插入其他公众号的文章。由此,我们即可获得采集文章的接口。

一、登陆微信公众号

在这里,我们使用 selenium + chromedriver(chrome 的 webdriver) 的方式来获取登陆的 cookie,这样,以后爬取文章时只需要载入 cookie 即可登陆。首先我们打开微信公众平台进行账号登陆:
1
我们用 insepect 检查获取登陆的账号、密码元素所在位置,来实现自动化登陆的目的 。

2

转化成代码如下:

# 用webdriver启动谷歌浏览器 print("启动浏览器,打开微信公众号登录界面") driver = webdriver.Chrome(executable_path='/usr/bin/chromedriver') # 此处 webdriver 根据自己的环境更改 # 打开微信公众号登录页面 driver.get('https://mp.weixin.qq.com/') # 等待5秒钟 time.sleep(5) print("正在输入微信公众号登录账号和密码......") #清空账号框中的内容 driver.find_element_by_name("account").clear() #自动填入登录用户名 driver.find_element_by_name("account").send_keys("输入你的公众号账号") #清空密码框中的内容 driver.find_element_by_name("password").clear() #自动填入登录密码 driver.find_element_by_name("password").send_keys("输入公众号密码") # 在自动输完密码之后需要手动点一下记住我 print("请在登录界面点击:记住账号") time.sleep(5) #自动点击登录按钮进行登录 driver.find_element_by_class_name("btn_login").click() # 拿手机扫二维码! print("请拿手机扫码二维码登录公众号") time.sleep(20) print("登录成功") # 用webdriver启动谷歌浏览器 print("启动浏览器,打开微信公众号登录界面") driver = webdriver.Chrome(executable_path='/usr/bin/chromedriver') # 此处 webdriver 根据自己的环境更改 # 打开微信公众号登录页面 driver.get('https://mp.weixin.qq.com/') # 等待5秒钟 time.sleep(5) print("正在输入微信公众号登录账号和密码......") #清空账号框中的内容 driver.find_element_by_name("account").clear() #自动填入登录用户名 driver.find_element_by_name("account").send_keys("输入你的公众号账号") #清空密码框中的内容 driver.find_element_by_name("password").clear() #自动填入登录密码 driver.find_element_by_name("password").send_keys("输入公众号密码") # 在自动输完密码之后需要手动点一下记住我 print("请在登录界面点击:记住账号") time.sleep(5) #自动点击登录按钮进行登录 driver.find_element_by_class_name("btn_login").click() # 拿手机扫二维码! print("请拿手机扫码二维码登录公众号") time.sleep(20) print("登录成功")

之后,我们需要重新登陆一次,保存 cookie,以后则载入 cookie 即可,不需要再扫码登陆。代码如下:

# 定义一个空的字典,存放cookies内容 post = {} driver.get('https://mp.weixin.qq.com/') # 获取cookies cookie_items = driver.get_cookies() # 获取到的cookies是列表形式,将cookies转成json形式并存入本地名为cookie的文本中 for cookie_item in cookie_items: post[cookie_item['name']] = cookie_item['value'] cookie_str = json.dumps(post) with open('cookie.txt', 'w+', encoding='utf-8') as f: f.write(cookie_str) print("cookies信息已保存到本地") # 定义一个空的字典,存放cookies内容 post = {} driver.get('https://mp.weixin.qq.com/') # 获取cookies cookie_items = driver.get_cookies() # 获取到的cookies是列表形式,将cookies转成json形式并存入本地名为cookie的文本中 for cookie_item in cookie_items: post[cookie_item['name']] = cookie_item['value'] cookie_str = json.dumps(post) with open('cookie.txt', 'w+', encoding='utf-8') as f: f.write(cookie_str) print("cookies信息已保存到本地")

之后我们开始文章的爬取。

二、爬取文章

根据官方描述,接口应该藏在新建图文素材中的插入超链接中,和之前爬取币乎一样,我们用 F12-Network-XHR 来跟踪这几个页面来获取我们需要配置的请求:
3

4

5

接下来,我们来配置请求参数:

#公众号主页 url = 'https://mp.weixin.qq.com' #设置headers header = { "HOST": "mp.weixin.qq.com", "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0" } #读取上一步获取到的cookies with open('cookie.txt', 'r', encoding='utf-8') as f: cookie = f.read() cookies = json.loads(cookie) #登录之后的微信公众号首页url变化为:https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token=1086424384,从这里获取token信息 response = requests.get(url=url, cookies=cookies) token = re.findall(r'token=(\d+)', str(response.url))[0] #搜索微信公众号的接口地址 search_url = 'https://mp.weixin.qq.com/cgi-bin/searchbiz?' #搜索微信公众号接口需要传入的参数,有三个变量:微信公众号token、随机数random、搜索的微信公众号名字query query_id = { 'action': 'search_biz', 'token' : token, 'lang': 'zh_CN', 'f': 'json', 'ajax': '1', 'random': random.random(), 'query': query, 'begin': '0', 'count': '5' } #打开搜索微信公众号接口地址,需要传入相关参数信息如:cookies、params、headers search_response = requests.get(search_url, cookies=cookies, headers=header, params=query_id) #取搜索结果中的第一个公众号 lists = search_response.json().get('list')[0] #获取这个公众号的fakeid,后面爬取公众号文章需要此字段 fakeid = lists.get('fakeid') #微信公众号文章接口地址 appmsg_url = 'https://mp.weixin.qq.com/cgi-bin/appmsg?' #搜索文章需要传入几个参数:登录的公众号token、要爬取文章的公众号fakeid、随机数random query_id_data = { 'token': token, 'lang': 'zh_CN', 'f': 'json', 'ajax': '1', 'random': random.random(), 'action': 'list_ex', 'begin': '0',#不同页,此参数变化,变化规则为每页加5 'count': '5', 'query': '', 'fakeid': fakeid, 'type': '9' } #打开搜索的微信公众号文章列表页 appmsg_response = requests.get(appmsg_url, cookies=cookies, headers=header, params=query_id_data) #公众号主页 url = 'https://mp.weixin.qq.com' #设置headers header = { "HOST": "mp.weixin.qq.com", "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0" } #读取上一步获取到的cookies with open('cookie.txt', 'r', encoding='utf-8') as f: cookie = f.read() cookies = json.loads(cookie) #登录之后的微信公众号首页url变化为:https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token=1086424384,从这里获取token信息 response = requests.get(url=url, cookies=cookies) token = re.findall(r'token=(\d+)', str(response.url))[0] #搜索微信公众号的接口地址 search_url = 'https://mp.weixin.qq.com/cgi-bin/searchbiz?' #搜索微信公众号接口需要传入的参数,有三个变量:微信公众号token、随机数random、搜索的微信公众号名字query query_id = { 'action': 'search_biz', 'token' : token, 'lang': 'zh_CN', 'f': 'json', 'ajax': '1', 'random': random.random(), 'query': query, 'begin': '0', 'count': '5' } #打开搜索微信公众号接口地址,需要传入相关参数信息如:cookies、params、headers search_response = requests.get(search_url, cookies=cookies, headers=header, params=query_id) #取搜索结果中的第一个公众号 lists = search_response.json().get('list')[0] #获取这个公众号的fakeid,后面爬取公众号文章需要此字段 fakeid = lists.get('fakeid') #微信公众号文章接口地址 appmsg_url = 'https://mp.weixin.qq.com/cgi-bin/appmsg?' #搜索文章需要传入几个参数:登录的公众号token、要爬取文章的公众号fakeid、随机数random query_id_data = { 'token': token, 'lang': 'zh_CN', 'f': 'json', 'ajax': '1', 'random': random.random(), 'action': 'list_ex', 'begin': '0',#不同页,此参数变化,变化规则为每页加5 'count': '5', 'query': '', 'fakeid': fakeid, 'type': '9' } #打开搜索的微信公众号文章列表页 appmsg_response = requests.get(appmsg_url, cookies=cookies, headers=header, params=query_id_data)

6

接下来,我们选择要爬取的公众号,进入文章列表界面:

7

8

9
分析第一页、第二页、第四百页,我们可以知道页码数由 begin 参数决定,且每一页 +5,初始页为 0。这样,我们可以通过对 begin 进行循环来爬取多个页数。

接下来,我们来查看每篇文章的信息藏在哪里:

10

点击右侧的 Preview,可以找出 app_msg_list 即可获取每篇文章的详细信息,接下来,我们就可以提取我们需要的信息,这里笔者提取了 title、link、update_time 方便之后存入数据库。

# 起始页 begin 参数,往后每页加 5 begin = 0 while begin <= 1995 : query_id_data = { 'token': token, 'lang': 'zh_CN', 'f': 'json', 'ajax': '1', 'random': random.random(), 'action': 'list_ex', 'begin': '{}'.format(str(begin)), 'count': '5', 'query': '', 'fakeid': fakeid, 'type': '9' } print('正在翻页:--------------',begin) # 获取每一页文章的标题和链接地址,并写入本地文本中 query_fakeid_response = requests.get(appmsg_url, cookies=cookies, headers=header, params=query_id_data) fakeid_list = query_fakeid_response.json().get('app_msg_list') for item in fakeid_list: content_link=item.get('link') content_title=item.get('title') content_time=item.get('update_time') fileName=query+'.txt' with open(fileName,'a',encoding='utf-8') as fh: fh.write(content_title+":\n"+content_link+"\n") begin = int(begin) begin += 5 time.sleep(20) # 起始页 begin 参数,往后每页加 5 begin = 0 while begin <= 1995 : query_id_data = { 'token': token, 'lang': 'zh_CN', 'f': 'json', 'ajax': '1', 'random': random.random(), 'action': 'list_ex', 'begin': '{}'.format(str(begin)), 'count': '5', 'query': '', 'fakeid': fakeid, 'type': '9' } print('正在翻页:--------------',begin) # 获取每一页文章的标题和链接地址,并写入本地文本中 query_fakeid_response = requests.get(appmsg_url, cookies=cookies, headers=header, params=query_id_data) fakeid_list = query_fakeid_response.json().get('app_msg_list') for item in fakeid_list: content_link=item.get('link') content_title=item.get('title') content_time=item.get('update_time') fileName=query+'.txt' with open(fileName,'a',encoding='utf-8') as fh: fh.write(content_title+":\n"+content_link+"\n") begin = int(begin) begin += 5 time.sleep(20)

至此,我们就可以将所爬取的公众号文章存入相应的 txt 文件,文本每三行为一篇文章,分别是标题、链接、发表时间。

最后,整合代码如下:

from selenium import webdriver import time import json import requests import re import random # 微信公众号账号 user = "输入你的公众号账号" # 公众号密码 password = "输入你的公众号密码" # 设置要爬取的公众号列表 query = '输入要爬取的公众号名字' # 登录微信公众号,获取登录之后的cookies信息,并保存到本地文本中 def weChat_login(): # 定义一个空的字典,存放cookies内容 post = {} # 用webdriver启动谷歌浏览器 print("启动浏览器,打开微信公众号登录界面") driver = webdriver.Chrome(executable_path='C:\chromedriver.exe') # 打开微信公众号登录页面 driver.get('https://mp.weixin.qq.com/') # 等待5秒钟 time.sleep(5) print("正在输入微信公众号登录账号和密码......") # 清空账号框中的内容 driver.find_element_by_name("account").clear() # 自动填入登录用户名 driver.find_element_by_name("account").send_keys(user) # 清空密码框中的内容 driver.find_element_by_name("password").clear() # 自动填入登录密码 driver.find_element_by_name("password").send_keys(password) # 在自动输完密码之后需要手动点一下记住我 print("请在登录界面点击:记住账号") time.sleep(10) # 自动点击登录按钮进行登录 driver.find_element_by_class_name("btn_login").click() # 拿手机扫二维码! print("请拿手机扫码二维码登录公众号") time.sleep(20) print("登录成功") # 重新载入公众号登录页,登录之后会显示公众号后台首页,从这个返回内容中获取cookies 信息 driver.get('https://mp.weixin.qq.com/') # 获取cookies cookie_items = driver.get_cookies() # 获取到的cookies是列表形式,将cookies转成json形式并存入本地名为cookie的文本中 for cookie_item in cookie_items: post[cookie_item['name']] = cookie_item['value'] cookie_str = json.dumps(post) with open('cookie.txt', 'w+', encoding='utf-8') as f: f.write(cookie_str) print("cookies信息已保存到本地") # 爬取微信公众号文章,并存在本地文本中 def get_content(query): # query为要爬取的公众号名称 # 公众号主页 url = 'https://mp.weixin.qq.com' # 设置headers header = { "HOST": "mp.weixin.qq.com", "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0" } # 读取上一步获取到的cookies with open('cookie.txt', 'r', encoding='utf-8') as f: cookie = f.read() cookies = json.loads(cookie) # 登录之后的微信公众号首页url变化为:https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token=1849751598,从这里获取token信息 response = requests.get(url=url, cookies=cookies) token = re.findall(r'token=(\d+)', str(response.url))[0] # 搜索微信公众号的接口地址 search_url = 'https://mp.weixin.qq.com/cgi-bin/searchbiz?' # 搜索微信公众号接口需要传入的参数,有三个变量:微信公众号token、随机数random、搜索的微信公众号名字 query_id = { 'action': 'search_biz', 'token': token, 'lang': 'zh_CN', 'f': 'json', 'ajax': '1', 'random': random.random(), 'query': query, 'begin': '0', 'count': '5' } # 打开搜索微信公众号接口地址,需要传入相关参数信息如:cookies、params、headers search_response = requests.get(search_url, cookies=cookies, headers=header,params=query_id) # 取搜索结果中的第一个公众号 lists = search_response.json().get('list')[0] # 获取这个公众号的fakeid,后面爬取公众号文章需要此字段 fakeid = lists.get('fakeid') # 微信公众号文章接口地址 appmsg_url = 'https://mp.weixin.qq.com/cgi-bin/appmsg?' # 起始页begin参数,往后每页加5 begin = 0 while begin <= 1995: # 此处循环终点需要根据所爬公众号调整 query_id_data = { 'token': token, 'lang': 'zh_CN', 'f': 'json', 'ajax': '1', 'random': random.random(), 'action': 'list_ex', 'begin': '{}'.format(str(begin)), 'count': '5', 'query': '', 'fakeid': fakeid, 'type': '9' } print('正在翻页:--------------', begin) # 获取每一页文章的标题和链接地址,并写入本地文本中 query_fakeid_response = requests.get(appmsg_url, cookies=cookies,headers=header,params=query_id_data) fakeid_list = query_fakeid_response.json().get('app_msg_list') for item in fakeid_list: content_link = item.get('link') content_title = item.get('title') content_time = item.get('update_time') fileName = query + '.txt' with open(fileName, 'a', encoding='utf-8') as fh: fh.write(content_title + ":\n" + content_link + "\n" + content_time + "\n") begin = int(begin) begin += 5 time.sleep(20) # 翻页时间过快或过多会被微信封锁此功能 24h if __name__ == '__main__': try: # 登录微信公众号,获取登录之后的cookies信息,并保存到本地文本中 # 第一次需要登陆,有了 cookie 后可以注释掉此句 weChat_login() # 登录之后,通过微信公众号后台提供的微信公众号文章接口爬取文章 # 爬取微信公众号文章,并存在本地文本中 print("开始爬取公众号:" + query) get_content(query) print("爬取完成") except Exception as e: print(str(e)) from selenium import webdriver import time import json import requests import re import random # 微信公众号账号 user = "输入你的公众号账号" # 公众号密码 password = "输入你的公众号密码" # 设置要爬取的公众号列表 query = '输入要爬取的公众号名字' # 登录微信公众号,获取登录之后的cookies信息,并保存到本地文本中 def weChat_login(): # 定义一个空的字典,存放cookies内容 post = {} # 用webdriver启动谷歌浏览器 print("启动浏览器,打开微信公众号登录界面") driver = webdriver.Chrome(executable_path='C:\chromedriver.exe') # 打开微信公众号登录页面 driver.get('https://mp.weixin.qq.com/') # 等待5秒钟 time.sleep(5) print("正在输入微信公众号登录账号和密码......") # 清空账号框中的内容 driver.find_element_by_name("account").clear() # 自动填入登录用户名 driver.find_element_by_name("account").send_keys(user) # 清空密码框中的内容 driver.find_element_by_name("password").clear() # 自动填入登录密码 driver.find_element_by_name("password").send_keys(password) # 在自动输完密码之后需要手动点一下记住我 print("请在登录界面点击:记住账号") time.sleep(10) # 自动点击登录按钮进行登录 driver.find_element_by_class_name("btn_login").click() # 拿手机扫二维码! print("请拿手机扫码二维码登录公众号") time.sleep(20) print("登录成功") # 重新载入公众号登录页,登录之后会显示公众号后台首页,从这个返回内容中获取cookies 信息 driver.get('https://mp.weixin.qq.com/') # 获取cookies cookie_items = driver.get_cookies() # 获取到的cookies是列表形式,将cookies转成json形式并存入本地名为cookie的文本中 for cookie_item in cookie_items: post[cookie_item['name']] = cookie_item['value'] cookie_str = json.dumps(post) with open('cookie.txt', 'w+', encoding='utf-8') as f: f.write(cookie_str) print("cookies信息已保存到本地") # 爬取微信公众号文章,并存在本地文本中 def get_content(query): # query为要爬取的公众号名称 # 公众号主页 url = 'https://mp.weixin.qq.com' # 设置headers header = { "HOST": "mp.weixin.qq.com", "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0" } # 读取上一步获取到的cookies with open('cookie.txt', 'r', encoding='utf-8') as f: cookie = f.read() cookies = json.loads(cookie) # 登录之后的微信公众号首页url变化为:https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token=1849751598,从这里获取token信息 response = requests.get(url=url, cookies=cookies) token = re.findall(r'token=(\d+)', str(response.url))[0] # 搜索微信公众号的接口地址 search_url = 'https://mp.weixin.qq.com/cgi-bin/searchbiz?' # 搜索微信公众号接口需要传入的参数,有三个变量:微信公众号token、随机数random、搜索的微信公众号名字 query_id = { 'action': 'search_biz', 'token': token, 'lang': 'zh_CN', 'f': 'json', 'ajax': '1', 'random': random.random(), 'query': query, 'begin': '0', 'count': '5' } # 打开搜索微信公众号接口地址,需要传入相关参数信息如:cookies、params、headers search_response = requests.get(search_url, cookies=cookies, headers=header,params=query_id) # 取搜索结果中的第一个公众号 lists = search_response.json().get('list')[0] # 获取这个公众号的fakeid,后面爬取公众号文章需要此字段 fakeid = lists.get('fakeid') # 微信公众号文章接口地址 appmsg_url = 'https://mp.weixin.qq.com/cgi-bin/appmsg?' # 起始页begin参数,往后每页加5 begin = 0 while begin <= 1995: # 此处循环终点需要根据所爬公众号调整 query_id_data = { 'token': token, 'lang': 'zh_CN', 'f': 'json', 'ajax': '1', 'random': random.random(), 'action': 'list_ex', 'begin': '{}'.format(str(begin)), 'count': '5', 'query': '', 'fakeid': fakeid, 'type': '9' } print('正在翻页:--------------', begin) # 获取每一页文章的标题和链接地址,并写入本地文本中 query_fakeid_response = requests.get(appmsg_url, cookies=cookies,headers=header,params=query_id_data) fakeid_list = query_fakeid_response.json().get('app_msg_list') for item in fakeid_list: content_link = item.get('link') content_title = item.get('title') content_time = item.get('update_time') fileName = query + '.txt' with open(fileName, 'a', encoding='utf-8') as fh: fh.write(content_title + ":\n" + content_link + "\n" + content_time + "\n") begin = int(begin) begin += 5 time.sleep(20) # 翻页时间过快或过多会被微信封锁此功能 24h if __name__ == '__main__': try: # 登录微信公众号,获取登录之后的cookies信息,并保存到本地文本中 # 第一次需要登陆,有了 cookie 后可以注释掉此句 weChat_login() # 登录之后,通过微信公众号后台提供的微信公众号文章接口爬取文章 # 爬取微信公众号文章,并存在本地文本中 print("开始爬取公众号:" + query) get_content(query) print("爬取完成") except Exception as e: print(str(e))

本次爬虫到这里就结束了。在下一篇图文中,将会分享如何配置自己的 webdriver 以及如何从已有的链接中提取文章正文。

提取正文链接

参考博文1
参考博文2