前段时间有个爬取公众号评论小需求,花了几天查了不少资料,实现方案有好几种,最后其中一种得以实现。参考 【Python爬虫】微信公众号历史文章和文章评论API分析 。

本人是 Python 小白,会忽略比较多的具体说明,只记录关键的几点,以便能快速实现 。给同样有兴趣的童鞋提供个浅显的参考。

也建议正在尝试的童鞋静下心来,一步步尝试下去,毕竟我这个小白都成功了呢。当然有错误的地方也欢迎指正。

使用环境:

Mac 、 Anaconda、MySQL 和 MySQL workbench。

很多博客里使用的 Windows 安装的 Python。但是 Mac 也没关系,Anaconda 传送门, MySQL传送门, MySQL workbench 传送门。

Anaconda 中的 Spyder 用来运行 Python 代码;

MySQL 是连接 Python 运行结果和数据库的桥梁 (这个有个坑点:安装 MySQL 只是作为一个桥梁,并不能作为数据库使用,所以要创建数据库,否则会报错);

MySQL workbench 用来创建、查看数据库,并可以到处 csv 格式的文件。

准备工作

首先需要提供公众号文章列表链接和评论链接,用于分析修改 Python 代码(具体的 Python 代码实现,我只看懂了流程,但是不会写)。那么就需要抓包了,有一些博客是使用 Fiddler,不过我使用 Charles 也完全足够了。只要能拿到接口相关数据即可。(不会抓包的请自行查阅资料)

公众号文章列表流程:打开要爬取的公众号 - 点击右上角的 '人物' 图标 - 点击 '消息'底部的 '全部消息'

尝试了几次,刚打开文章列表,并没有文章列表的接口,可以上拉刷新一下。

文章列表抓包截图

文章列表抓包示意图.png

文章评论抓包截图

评论抓包示意图 1.png

评论数据示意图.png

我需要的就是 elected_comment 列表中每个 Object 中的 content 内容。Python 代码已实现获取逻辑。

Python 代码中需要提供接口中的几个参数:__biz、pass_ticket、app_msg_token、wap_sid2 和 cookie。具体作用可参顶部博客的说明。

正式爬数据

提供代码中所需的几个字段后,可以在 Anaconda 中的 Spyder 运行 Python 代码(代码在文末),然后替换其中的字段。即下面的几个字

biz = 'MzIwNTc4NTEwOQ==' # "码农有道公众号" mnyd_article mnyd_comment

pass_ticket = 'ZS3nqLX1df5GhZ+zf/t0FYyf7Nfp52yUJ+PuyJUKvQtyln78R3QzBU21Xo528IE+'

app_msg_token = '986_G0Sy%252FL2pNlAGA9PIXcqTRipxsKaGLurexidEyg~~' # 历史文章

wap_sid2 = 'CL3qgfIFElxMOFBzZ2dZOHQ1WTcxamRQLXUyMGFiU0tvNkZzUEJmRURhZmtJTkhLcEtYWU9rNm5WYmUtd29qd3Q3UmVqbmpZXzFxS21GMG13amVjM1NEaUVPajZNZG9EQUFBfjDH8K3gBTgNQAE='

cookie = 'wxuin=1581282621; version=2607033b; pass_ticket={}; wap_sid2={}'.format(pass_ticket, wap_sid2)

在开始运行代码后开始遇到问题:

1 ModuleNotFoundError: No module named 'pymysql';

需要安装数据库,比如安装 MySQL。

然后在代码中替换自己的密码

self.db = pymysql.connect(

host="localhost",

user="root",

password="123456",

port=3306,

use_unicode=True,

#charset="utf8",

database="sunshine")

self.cursor = self.db.cursor()

2 需要创建数据库,比如代码中数据库名字为 sunshine;

3 代码中 offset 大部分是 10,不过有些公众号是 20,但是 10 也可以正常运行,不用担心;

4 因为是模拟手机接口,爬取完数据后可能会出现 '操作频繁,请稍后再试',这个没有关系,等下再刷新就正常了。

基本上 Anaconda 等软件安装正确,数据库已安装,抓包数据没错,替换 biz 等参数,替换数据库配置密码(或数据库名),是可以正常运行并且保存至数据库。

注意

Python 代码中需要修改的,都以 # ** 提示

当时比较紧急,很多错误没有保存,现在回忆也零零散散。有需要的凑合看参考下吧。

发布文章要既要绑定手机号又要绑定微信,让人很不爽 (小声BB)

代码示例

作者: cacho_37967865

# -!- coding: utf-8 -!-

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

#作者:cacho_37967865

#博客:https://blog.csdn.net/sinat_37967865

#文件:wechatArticleList.py

#日期:2018-12-08

#备注:通过Fiddler抓包,获取微信公众号历史文章信息和文章评论信息存储到mysql数据库表

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

import requests

import json

import pymysql

from datetime import datetime

import re

class wechatArticle:

def __init__(self,_biz,_pass_ticket,_appmsg_token,_cookie,_offset=0):

self.offset = _offset # 不同公众号不一样

self.biz = _biz

self.pass_ticket = _pass_ticket

self.appmsg_token = _appmsg_token

self.headers = {

'cookie':_cookie,

'User-Agent':'Mozilla/5.0 (Linux; Android 8.0; FRD-AL00 Build/HUAWEIFRD-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132'

}

self.db = pymysql.connect(

# ** password 需要替换为自己的。数据库名 database 视情况,是否修改看个人需要

host="localhost",

user="root",

password="123456",

port=3306,

use_unicode=True,

#charset="utf8",

database="sunshine")

self.cursor = self.db.cursor()

def get_article_list(self):

offset = self.offset

while True:

api = 'https://mp.weixin.qq.com/mp/profile_ext?action=getmsg&__biz={0}&f=json&offset={1}&count=10&is_ok=1&scene=126&uin=777&key=777&pass_ticket={2}&wxtoken=&appmsg_token={3}&x5=1&f=json'.format(self.biz, offset, self.pass_ticket, self.appmsg_token)

resp = requests.get(api, headers=self.headers).json()

print(type(resp), resp) # 字典类型

ret, status = resp.get('ret'), resp.get('errmsg') # 状态信息

if ret == 0 or status == 'ok':

offset = resp['next_offset']

general_msg_list = resp['general_msg_list']

#print(type(general_msg_list),general_msg_list) # json类型

msg_list = json.loads(general_msg_list)['list'] # 先转化为字典类型再获取列表类型

for msg in msg_list:

comm_msg_info = msg['comm_msg_info'] # 字典类型,每次推送的消息(一次三篇)

msg_id = comm_msg_info['id'] # 推送消息的id

post_time = datetime.fromtimestamp(comm_msg_info['datetime']) # 发布时间

try:

app_msg_ext_info = msg['app_msg_ext_info'] # 字典类型,文章信息(一次三篇)

first_article_id = app_msg_ext_info['fileid']

first_article_title = app_msg_ext_info['title'] # 本次推送的首条文章标题

first_article_digest = app_msg_ext_info['digest'] # 本次推送的首条文章摘要

first_article_url = app_msg_ext_info['content_url']

self.get_article_detail(first_article_id,first_article_url)

first_url = first_article_url.replace('amp;', '').split('&chksm')[0]

self.article_to_mysql(msg_id, first_article_id, first_article_title, first_article_digest,first_url, post_time)

multi_app_msg_item_list = app_msg_ext_info.get('multi_app_msg_item_list')

for article in multi_app_msg_item_list:

article_id = article['fileid']

multi_article_title = article['title']

multi_article_digest = article['digest']

multi_article_url = article['content_url']

self.get_article_detail(article_id,multi_article_url)

multi_url = multi_article_url.replace('amp;', '').split('&chksm')[0]

self.article_to_mysql(msg_id, article_id, multi_article_title, multi_article_digest,multi_url, post_time)

except Exception as f:

print(str(f))

def get_article_detail(self,article_id,content_url):

try:

url = content_url.replace('amp;', '').replace('#wechat_redirect', '').replace('http', 'https')

html = requests.get(url, headers=self.headers).text

#print(html)

except:

print('获取评论失败' + content_url)

else:

str_comment = re.search(r'var comment_id = "(.*)" \|\| "(.*)" \* 1;', html)

str_msg = re.search(r"var appmsgid = '' \|\| '(.*)'\|\|", html) # 文章的id

str_token = re.search(r'window.appmsg_token = "(.*)";', html)

if str_comment and str_msg and str_token:

comment_id = str_comment.group(1) # 评论id(固定)

app_msg_id = str_msg.group(1) # 票据id(非固定)

appmsg_token = str_token.group(1) # 票据token(非固定)

# 缺一不可

if comment_id and app_msg_id and appmsg_token:

print("爬取评论的链接:" + url,html)

self.get_article_comments(app_msg_id,comment_id,appmsg_token,article_id)

def get_article_comments(self,app_msg_id,comment_id,appmsg_token,article_id):

api = 'https://mp.weixin.qq.com/mp/appmsg_comment?action=getcomment&scene=0&__biz={0}&appmsgid={1}&idx=2&comment_id={2}&offset=0&limit=100&uin=777&key=777&pass_ticket={3}&wxtoken=777&devicetype=android-26&clientversion=2607033b&appmsg_token={4}&x5=1&f=json'.format(

self.biz, app_msg_id, comment_id, self.pass_ticket, appmsg_token)

resp = requests.get(api, headers=self.headers).json()

ret, status = resp['base_resp']['ret'], resp['base_resp']['errmsg']

if ret =='0' or status == 'ok':

elected_comment = resp['elected_comment']

for comment in elected_comment:

content_id = comment.get('content_id') # 评论ID

nick_name = comment.get('nick_name') # 评论人昵称

like_num = comment.get('like_num') # 点赞

comment_time = datetime.fromtimestamp(comment.get('create_time')) # 评论时间

content = comment.get('content') # 评论内容

#print("评论内容文章:",article_id,nick_name)

self.comment_to_mysql(article_id,content_id,comment_time,nick_name,like_num,content)

def create_article_table(self):

sql1 = 'drop table if exists mnyd_article;'

sql2 = 'create table mnyd_article(No INT(11) NOT NULL AUTO_INCREMENT,msg_id VARCHAR(15),article_id VARCHAR(15),post_time timestamp(2),title VARCHAR(200),digest VARCHAR(200),article_url varchar(300),PRIMARY KEY (No));'

self.cursor.execute(sql1)

self.cursor.execute(sql2)

self.db.commit()

def article_to_mysql(self,msg_id, article_id,title,digest,article_url,post_time):

sql = "insert into mnyd_article(msg_id,article_id,title,digest,article_url,post_time) values('%s','%s','%s','%s','%s','%s')" % (msg_id,article_id,title, digest,article_url,post_time)

try:

# 使用 cursor() 方法创建一个游标对象 cursor

self.cursor.execute(sql)

except Exception as e:

# 发生错误时回滚

self.db.rollback()

print(str(e))

else:

self.db.commit() # 事务提交

print('事务处理成功')

def create_comment_table(self):

sql1 = 'drop table if exists mnyd_comment;'

sql2 = "create table mnyd_comment(No INT(11) NOT NULL AUTO_INCREMENT,article_id VARCHAR(15),content_id VARCHAR(20),comment_time timestamp(2),nick_name VARCHAR(50),like_num int,content varchar(1000),PRIMARY KEY (No)) COLLATE='utf8mb4_unicode_ci';"

self.cursor.execute(sql1)

self.cursor.execute(sql2)

self.db.commit()

def comment_to_mysql(self,article_id,content_id,comment_time,nick_name,like_num,content):

sql = "insert into mnyd_comment(article_id,content_id,comment_time,nick_name,like_num,content) values('%s','%s','%s','%s','%i','%s')" % (article_id,content_id,comment_time, nick_name,like_num,content)

try:

# 使用 cursor() 方法创建一个游标对象 cursor

self.cursor.execute(sql)

except Exception as e:

# 发生错误时回滚

self.db.rollback()

print(str(e))

else:

self.db.commit() # 事务提交

print('事务处理成功')

if __name__ == '__main__':

# ** 以下几个字段需要替换为自己需要的,每个公众号都是不同的

biz = 'MzIwNTc4NTEwOQ==' # "码农有道公众号" mnyd_article mnyd_comment

pass_ticket = 'ZS3nqLX1df5GhZ+zf/t0FYyf7Nfp52yUJ+PuyJUKvQtyln78R3QzBU21Xo528IE+'

app_msg_token = '986_G0Sy%252FL2pNlAGA9PIXcqTRipxsKaGLurexidEyg~~' # 历史文章

wap_sid2 = 'CL3qgfIFElxMOFBzZ2dZOHQ1WTcxamRQLXUyMGFiU0tvNkZzUEJmRURhZmtJTkhLcEtYWU9rNm5WYmUtd29qd3Q3UmVqbmpZXzFxS21GMG13amVjM1NEaUVPajZNZG9EQUFBfjDH8K3gBTgNQAE='

cookie = 'wxuin=1581282621; version=2607033b; pass_ticket={}; wap_sid2={}'.format(pass_ticket, wap_sid2)

# 以上信息不同公众号每次抓取都需要借助抓包工具做修改

wxarticles = wechatArticle(biz, pass_ticket, app_msg_token, cookie)

wxarticles.create_article_table() # 创建数据库表记录文章

wxarticles.create_comment_table() # 创建数据库表记录评论

wxarticles.get_article_list() # 开始爬取文章和评论

python公众号留言功能_Python 爬取公众号文章、评论相关推荐

  1. python爬取网易云评论最多的歌_python爬取网易云音乐评论

    本文实例为大家分享了python爬取网易云音乐评论的具体代码,供大家参考,具体内容如下 import requests import bs4 import json def get_hot_comme ...

  2. 2023年微信公众号留言功能怎么开启?公众号留言功能怎么开通

    为什么我的公众号没有留言功能?2023年最新微信公众号留言功能开通手册 很多朋友想要开启公众号的留言功能,但却不知道该如何操作,本篇文章说说与其相关的知识. 公众号留言功能怎么开启? 根据微信官方给出 ...

  3. python爬取评论_python爬取网易云音乐评论

    本文实例为大家分享了python爬取网易云音乐评论的具体代码,供大家参考,具体内容如下 import requests import bs4 import json def get_hot_comme ...

  4. python爬携程景区评论_python爬取携程景点评论信息

    python爬取携程景点评论信息 今天要分析的网站是携程网,获取景点的用户评论,评论信息通过json返回API,页面是这个样子的 按下F12之后,F5刷新一下 具体需要URL Request的方式为P ...

  5. python爬取网易云音乐热评_python爬取网易云音乐评论

    本文实例为大家分享了python爬取网易云音乐评论的具体代码,供大家参考,具体内容如下 import requests import bs4 import json def get_hot_comme ...

  6. python爬取网易云音乐评论分析_python爬取网易云音乐评论

    本文实例为大家分享了python爬取网易云音乐评论的具体代码,供大家参考,具体内容如下 import requests import bs4 import json def get_hot_comme ...

  7. 用python爬取网易云评论_python爬取网易云音乐评论

    本文实例为大家分享了python爬取网易云音乐评论的具体代码,供大家参考,具体内容如下 import requests import bs4 import json def get_hot_comme ...

  8. python实现qq登录腾讯视频_Python爬取腾讯视频评论的思路详解

    一.前提条件 安装了Fiddler了(用于抓包分析) 谷歌或火狐浏览器 如果是谷歌浏览器,还需要给谷歌浏览器安装一个SwitchyOmega插件,用于代理服务器 有Python的编译环境,一般选择Py ...

  9. python爬虫公众号音频源代码_python爬取音频下载的示例代码

    抓取"xmly"鬼故事音频 import json # 在这个url,音频链接为JSON动态生成,所以用到了json模块 import requests headers = { & ...

最新文章

  1. Oracle Start With关键字
  2. AAC规格分类和下载地址
  3. oracle cost小 比较慢,Oracle数据库中有关CBO优化的三个问题
  4. 计算机专业方面的论文,计算机专业毕业论文
  5. structed streaming基础---跳过的坑
  6. 图像处理之给定任意四点不规则放缩
  7. sqlmap入门使用教程
  8. photoshop 插件_Photoshop的线性光
  9. HTML5+CSS大作业——清新春暖花开个人博客网站(6页)
  10. 蒟蒻の背包dp学习总结
  11. 下一代Windows命名为Win 11?微软的下一步要来了
  12. USB通信协议与供电协议全解
  13. dell服务器1950安装win7系统,DELLOPTIPLEX3040安装WIN7操作系统方法图文
  14. Web前端是什么?主要是干什么的
  15. wxc-cell使用
  16. 周鸿祎刘强东等互联网大佬最失败的创业项目
  17. 进程死锁终结者——银行家算法
  18. 人的一生就是在不断的学习中成长
  19. ansible学习系列之顺利启动后台程序
  20. 师生使用计算机网络 应当遵循,大学生安全教育试题

热门文章

  1. Dowiedz si? wi?cej o Nike Free Run
  2. VTP-------详解
  3. [PLC]ST语言一:LD_LDI_AND_ANI_OR_ORI
  4. ilove中文_I Love You,答えてくれ中文歌词翻译
  5. 远程桌面由于以下原因之一无法连接到远程计算机
  6. 【eclipse】版本代号
  7. 艾宾浩斯记忆遗忘曲线
  8. 100万补贴!东湖高新区知识产权运营服务体系建设项目申报时间、条件流程大全
  9. 使用搜狐云景部署Ghost博客
  10. How to caching Global data in on-chip (level 1) cache in Morden GPU