时间:2022-07-24 01:18:01 | 来源:网站运营
时间:2022-07-24 01:18:01 来源:网站运营
2019年10月28日更新:http://mp.weixin.qq.com/mp/getmasssendmsg?__biz=MjM5MzczNjY2NA==#wechat_webview_type=1&wechat_redirect
=========2017年1月11日更新=========https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzA3NDk5MjYzNg==&scene=124#wechat_redirect
//第一种链接http://mp.weixin.qq.com/mp/getmasssendmsg?__biz=MjM5NTM1NjczMw==&uin=NzM4MTk1ODgx&key=a226a081696afed0d9dfa0972fa431e116e5c4572ce52343178ad4e9a2b94aeaad6ac4dd87de3e56f72209a73a32e9cc2052f68aca4884e36cf726e99f2671630c741d8e4c29abe4a049d1a71eeb2be5&devicetype=android-17&version=2605033c&lang=zh_CN&nettype=WIFI&ascene=1&pass_ticket=zbA7PswOPKySRpyEYI5kDCjRiljxcpzdbTuVMauFGemgdp8R1DY1uQY49srehWab&wx_header=1//第二种http://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzA3NDk5MjYzNg==&scene=124&uin=NzM4MTk1ODgx&key=5134ab1cc362a0324183dbd55a2680d11ccbaa34cdb349ee9be58f5b666092ddb17adf8a88dc788831923f3c6087547d651f04209f72334d511c9e118a3800d7b05a324a38903f79cff940cf749ecd5a&devicetype=android-17&version=2605033c&lang=zh_CN&nettype=WIFI&a8scene=3&pass_ticket=Fo3zjtJcbPfijNHKUIQbV%2BeHsAqhbjJCwzTfV48u%2FCZRRGTmI8oqmHDxxfEL8ke%2B&wx_header=1
这个地址是通过微信客户端打开历史消息页面之后,再使用后面介绍的代理服务器软件获取到的。这里面有几个参数:replaceServerResDataAsync: function(req,res,serverResData,callback){ if(/mp//getmasssendmsg/i.test(req.url)){//当链接地址为公众号历史消息页面时(第一种页面形式) if(serverResData.toString() !== ""){ try {//防止报错退出程序 var reg = /msgList = (.*?);/;//定义历史消息正则匹配规则 var ret = reg.exec(serverResData.toString());//转换变量为string HttpPost(ret[1],req.url,"getMsgJson.php");//这个函数是后文定义的,将匹配到的历史消息json发送到自己的服务器 var http = require('http'); http.get('http://xxx.com/getWxHis.php', function(res) {//这个地址是自己服务器上的一个程序,目的是为了获取到下一个链接地址,将地址放在一个js脚本中,将页面自动跳转到下一页。后文将介绍getWxHis.php的原理。 res.on('data', function(chunk){ callback(chunk+serverResData);//将返回的代码插入到历史消息页面中,并返回显示出来 }) }); }catch(e){//如果上面的正则没有匹配到,那么这个页面内容可能是公众号历史消息页面向下翻动的第二页,因为历史消息第一页是html格式的,第二页就是json格式的。 try { var json = JSON.parse(serverResData.toString()); if (json.general_msg_list != []) { HttpPost(json.general_msg_list,req.url,"getMsgJson.php");//这个函数和上面的一样是后文定义的,将第二页历史消息的json发送到自己的服务器 } }catch(e){ console.log(e);//错误捕捉 } callback(serverResData);//直接返回第二页json内容 } } }else if(/mp//profile_ext/?action=home/i.test(req.url)){//当链接地址为公众号历史消息页面时(第二种页面形式) try { var reg = /var msgList = /'(.*?)/';/;//定义历史消息正则匹配规则(和第一种页面形式的正则不同) var ret = reg.exec(serverResData.toString());//转换变量为string HttpPost(ret[1],req.url,"getMsgJson.php");//这个函数是后文定义的,将匹配到的历史消息json发送到自己的服务器 var http = require('http'); http.get('http://xxx.com/getWxHis', function(res) {//这个地址是自己服务器上的一个程序,目的是为了获取到下一个链接地址,将地址放在一个js脚本中,将页面自动跳转到下一页。后文将介绍getWxHis.php的原理。 res.on('data', function(chunk){ callback(chunk+serverResData);//将返回的代码插入到历史消息页面中,并返回显示出来 }) }); }catch(e){ callback(serverResData); } }else if(/mp//profile_ext/?action=getmsg/i.test(req.url)){//第二种页面表现形式的向下翻页后的json try { var json = JSON.parse(serverResData.toString()); if (json.general_msg_list != []) { HttpPost(json.general_msg_list,req.url,"getMsgJson.php");//这个函数和上面的一样是后文定义的,将第二页历史消息的json发送到自己的服务器 } }catch(e){ console.log(e); } callback(serverResData); }else if(/mp//getappmsgext/i.test(req.url)){//当链接地址为公众号文章阅读量和点赞量时 try { HttpPost(serverResData,req.url,"getMsgExt.php");//函数是后文定义的,功能是将文章阅读量点赞量的json发送到服务器 }catch(e){ } callback(serverResData); }else if(/s/?__biz/i.test(req.url) || /mp//rumor/i.test(req.url)){//当链接地址为公众号文章时(rumor这个地址是公众号文章被辟谣了) try { var http = require('http'); http.get('http://xxx.com/getWxPost.php', function(res) {//这个地址是自己服务器上的另一个程序,目的是为了获取到下一个链接地址,将地址放在一个js脚本中,将页面自动跳转到下一页。后文将介绍getWxPost.php的原理。 res.on('data', function(chunk){ callback(chunk+serverResData); }) }); }catch(e){ callback(serverResData); } }else{ callback(serverResData); } },
function HttpPost(str,url,path) {//将json发送到服务器,str为json内容,url为历史消息页面地址,path是接收程序的路径和文件名 var http = require('http'); var data = { str: encodeURIComponent(str), url: encodeURIComponent(url) }; content = require('querystring').stringify(data); var options = { method: "POST", host: "www.xxx.com",//注意没有http://,这是服务器的域名。 port: 80, path: path,//接收程序的路径和文件名 headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', "Content-Length": content.length } }; var req = http.request(options, function (res) { res.setEncoding('utf8'); res.on('data', function (chunk) { console.log('BODY: ' + chunk); }); }); req.on('error', function (e) { console.log('problem with request: ' + e.message); }); req.write(content); req.end();}
上面就是rule规则修改的主要部分,需要将json内容发送到自己的服务器,还要从服务器获取到下一页的跳转地址。这就涉及到了四个php文件:getMsgJson.php、getMsgExt.php、getWxHis.php、getWxPost.phpreplaceRequestOption : function(req,option){ var newOption = option; if(/google/i.test(newOption.headers.host)){ newOption.hostname = "www.baidu.com"; newOption.port = "80"; } return newOption; },
以上就是针对anyproxy的rule文件的修改配置,配置修改完成之后,重新启动anyproxy。mac系统里按control+c中断程序,再输入命令sudo anyproxy -i启动;如果启动报错,可能是程序没有退出干净,端口被占用。这时输入命令ps -a查看占用的pid,再输入命令“kill -9 pid”这里将pid替换成查询到的pid号码。杀死进程之后就可以启动anyproxy了。还是那句话windows的命令请原谅我不太熟悉。<?$str = $_POST['str'];$url = $_POST['url'];//先获取到两个POST变量//先针对url参数进行操作parse_str(parse_url(htmlspecialchars_decode(urldecode($url)),PHP_URL_QUERY ),$query);//解析url地址$biz = $query['__biz'];//得到公众号的biz//接下来进行以下操作//从数据库中查询biz是否已经存在,如果不存在则插入,这代表着我们新添加了一个采集目标公众号。//再解析str变量$json = json_decode($str,true);//首先进行json_decodeif(!$json){ $json = json_decode(htmlspecialchars_decode($str),true);//如果不成功,就增加一步htmlspecialchars_decode}foreach($json['list'] as $k=>$v){ $type = $v['comm_msg_info']['type']; if($type==49){//type=49代表是图文消息 $content_url = str_replace("//", "", htmlspecialchars_decode($v['app_msg_ext_info']['content_url']));//获得图文消息的链接地址 $is_multi = $v['app_msg_ext_info']['is_multi'];//是否是多图文消息 $datetime = $v['comm_msg_info']['datetime'];//图文消息发送时间 //在这里将图文消息链接地址插入到采集队列库中(队列库将在后文介绍,主要目的是建立一个批量采集队列,另一个程序将根据队列安排下一个采集的公众号或者文章内容) //在这里根据$content_url从数据库中判断一下是否重复 if('数据库中不存在相同的$content_url') { $fileid = $v['app_msg_ext_info']['fileid'];//一个微信给的id $title = $v['app_msg_ext_info']['title'];//文章标题 $title_encode = urlencode(str_replace(" ", "", $title));//建议将标题进行编码,这样就可以存储emoji特殊符号了 $digest = $v['app_msg_ext_info']['digest'];//文章摘要 $source_url = str_replace("//", "", htmlspecialchars_decode($v['app_msg_ext_info']['source_url']));//阅读原文的链接 $cover = str_replace("//", "", htmlspecialchars_decode($v['app_msg_ext_info']['cover']));//封面图片 $is_top = 1;//标记一下是头条内容 //现在存入数据库 echo "头条标题:".$title.$lastId."/n";//这个echo可以显示在anyproxy的终端里 } if($is_multi==1){//如果是多图文消息 foreach($v['app_msg_ext_info']['multi_app_msg_item_list'] as $kk=>$vv){//循环后面的图文消息 $content_url = str_replace("//","",htmlspecialchars_decode($vv['content_url']));//图文消息链接地址 //这里再次根据$content_url判断一下数据库中是否重复以免出错 if('数据库中不存在相同的$content_url'){ //在这里将图文消息链接地址插入到采集队列库中(队列库将在后文介绍,主要目的是建立一个批量采集队列,另一个程序将根据队列安排下一个采集的公众号或者文章内容) $title = $vv['title'];//文章标题 $fileid = $vv['fileid'];//一个微信给的id $title_encode = urlencode(str_replace(" ","",$title));//建议将标题进行编码,这样就可以存储emoji特殊符号了 $digest = htmlspecialchars($vv['digest']);//文章摘要 $source_url = str_replace("//","",htmlspecialchars_decode($vv['source_url']));//阅读原文的链接 //$cover = getCover(str_replace("//","",htmlspecialchars_decode($vv['cover']))); $cover = str_replace("//","",htmlspecialchars_decode($vv['cover']));//封面图片 //现在存入数据库 echo "标题:".$title.$lastId."/n"; } } } } }?>
再次强调代码只是原理,其中一部分注视的代码要自己编写。<?$str = $_POST['str'];$url = $_POST['url'];//先获取到两个POST变量//先针对url参数进行操作parse_str(parse_url(htmlspecialchars_decode(urldecode($url)),PHP_URL_QUERY ),$query);//解析url地址$biz = $query['__biz'];//得到公众号的biz$sn = $query['sn'];//再解析str变量$json = json_decode($str,true);//进行json_decode//$sql = "select * from `文章表` where `biz`='".$biz."' and `content_url` like '%".$sn."%'" limit 0,1;//根据biz和sn找到对应的文章$read_num = $json['appmsgstat']['read_num'];//阅读量$like_num = $json['appmsgstat']['like_num'];//点赞量//在这里同样根据sn在采集队列表中删除对应的文章,代表这篇文章可以移出采集队列了//$sql = "delete from `队列表` where `content_url` like '%".$sn."%'" //然后将阅读量和点赞量更新到文章表中。exit(json_encode($msg));//可以显示在anyproxy的终端里?>
3、getWxHis.php、getWxPost.php两个程序比较类似,一起介绍<?//getWxHis.php 当前页面为公众号历史消息时,读取这个程序//在采集队列表中有一个load字段,当值等于1时代表正在被读取//首先删除采集队列表中load=1的行//然后从队列表中任意select一行if('队列表为空'){ //队列表如果空了,就从存储公众号biz的表中取得一个biz,这里我在公众号表中设置了一个采集时间的time字段,按照正序排列之后,就得到时间戳最小的一个公众号记录,并取得它的biz $url = "http://mp.weixin.qq.com/mp/getmasssendmsg?__biz=".$biz."#wechat_webview_type=1&wechat_redirect";//拼接公众号历史消息url地址(第一种页面形式) $url = "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=".$biz."&scene=124#wechat_redirect";//拼接公众号历史消息url地址(第二种页面形式) //更新刚才提到的公众号表中的采集时间time字段为当前时间戳。}else{ //取得当前这一行的content_url字段 $url = $content_url; //将load字段update为1}echo "<script>setTimeout(function(){window.location.href='".$url."';},2000);</script>";//将下一个将要跳转的$url变成js脚本,由anyproxy注入到微信页面中。?><?//getWxPost.php 当前页面为公众号文章页面时,读取这个程序//首先删除采集队列表中load=1的行//然后从队列表中按照“order by id asc”选择多行(注意这一行和上面的程序不一样) if(!empty('队列表') && count('队列表中的行数')>1){//(注意这一行和上面的程序不一样) //取得第0行的content_url字段 $url = $content_url; //将第0行的load字段update为1 }else{ //队列表还剩下最后一条时,就从存储公众号biz的表中取得一个biz,这里我在公众号表中设置了一个采集时间的time字段,按照正序排列之后,就得到时间戳最小的一个公众号记录,并取得它的biz $url = "http://mp.weixin.qq.com/mp/getmasssendmsg?__biz=".$biz."#wechat_webview_type=1&wechat_redirect";//拼接公众号历史消息url地址(第一种页面形式) $url = "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=".$biz."&scene=124#wechat_redirect";//拼接公众号历史消息url地址(第二种页面形式) //更新刚才提到的公众号表中的采集时间time字段为当前时间戳。 } echo "<script>setTimeout(function(){window.location.href='".$url."';},2000);</script>";//将下一个将要跳转的$url变成js脚本,由anyproxy注入到微信页面中。?>
这两段程序的意义是:从队列表中读取出下一个采集内容的信息,如果是历史消息页,则将biz拼接到地址中(注意:评论区有朋友以为key和pass_ticket也要拼接,实则不需要),通过js的方式输出到页面,如果下一条是文章,则将历史消息列表json中的文章地址直接输出为js。同样文章内容的地址中不包含uin和key这样的参数,这些参数都是由客户端自动补充的。CREATE TABLE `weixin` ( `id` int(11) NOT NULL AUTO_INCREMENT, `biz` varchar(255) DEFAULT '' COMMENT '公众号唯一标识biz', `collect` int(11) DEFAULT '1' COMMENT '记录采集时间的时间戳', PRIMARY KEY (`id`)) ;
2、微信文章表CREATE TABLE `post` ( `id` int(11) NOT NULL AUTO_INCREMENT, `biz` varchar(255) CHARACTER SET utf8 NOT NULL COMMENT '文章对应的公众号biz', `field_id` int(11) NOT NULL COMMENT '微信定义的一个id,每条文章唯一', `title` varchar(255) NOT NULL DEFAULT '' COMMENT '文章标题', `title_encode` text CHARACTER SET utf8 NOT NULL COMMENT '文章编码,防止文章出现emoji', `digest` varchar(500) NOT NULL DEFAULT '' COMMENT '文章摘要', `content_url` varchar(500) CHARACTER SET utf8 NOT NULL COMMENT '文章地址', `source_url` varchar(500) CHARACTER SET utf8 NOT NULL COMMENT '阅读原文地址', `cover` varchar(500) CHARACTER SET utf8 NOT NULL COMMENT '封面图片', `is_multi` int(11) NOT NULL COMMENT '是否多图文', `is_top` int(11) NOT NULL COMMENT '是否头条', `datetime` int(11) NOT NULL COMMENT '文章时间戳', `readNum` int(11) NOT NULL DEFAULT '1' COMMENT '文章阅读量', `likeNum` int(11) NOT NULL DEFAULT '0' COMMENT '文章点赞量', PRIMARY KEY (`id`)) ;
3、采集队列表CREATE TABLE `tmplist` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `content_url` varchar(255) DEFAULT NULL COMMENT '文章地址', `load` int(11) DEFAULT '0' COMMENT '读取中标记', PRIMARY KEY (`id`), UNIQUE KEY `content_url` (`content_url`)) ;
以上就是由微信客户端、微信号、anyproxy代理服务器、PHP程序、mysql数据库共同组成的微信公众号文章批量自动采集系统。关键词:采集,系统,文章,更新,公众,持续