详细Java批量获取微信公众号方法

网友投稿 177 2023-03-09


详细Java批量获取微信公众号方法

系统的基本思路是在安卓模拟器上运行微信,模拟器设置代理,通过代理服务器拦截微信数据,将得到的数据发送给自己的程序进行处理。

需要准备的环境:nodejs,anyproxy代理,安卓模拟器

nodejs下载地址:http://nodejs.cn/download/,我下载的是windows版的,下好直接安装就行。安装好后,直接运行C:\Program Files\nodejs\npm.cmd 会自动配置好环境。

anyproxy安装:按上一步安装好nodejs之后,直接在cmd运行 npm install -g anyproxy 就会安装了

安卓模拟器随便在网上下一个就好了,一大堆。

首先为代理服务器安装证书,anyproxy默认不解析https链接,安装证书后就可以解析了,在cmd执行anyproxy --root 就会安装证书,之后还得在模拟器也下载这个证书。

然后输入anyproxy -i 命令 打开代理服务。(记得加上参数!)

记住这个ip和端口,之后安卓模拟器的代理就用这个。现在用浏览器打开网页:http://localhost:8002/  这是anyproxy的网页界面,用于显示http传输数据。

点击上面红框框里面的菜单,会出一个二维码,用安卓模拟器扫码识别,模拟器(手机)就会下载证书了,安装上就好了。

现在准备为模拟器设置代理,代理方式设置为手动,代理ip为运行anyproxy机器的ip,端口是8001

上面红框内就是微信文章的链接,点击进去可以看到具体的数据。如果response body里面什么都没有可能证书安装有问题。

如果上面都走通了,就可以接着往下走了。

这里我们靠代理服务抓微信数据,但总不能抓取一条数据就自己操作一下微信,那样还不如直接人工复制。所以我们需要微信客户端自己跳转页面。这时就可以使用anyproxy拦截微信服务器返回的数据,往里面注入页面跳转代码,再把加工的数据返回给模拟器实现微信客户端自动跳转。

打开anyproxy中的一个叫rule_default.js的js文件,windows下该文件在:C:\Users\Administrator\AppData\Roaming\npm\node_modules\anyproxy\lib

在文件里面有个叫replaceServerResDataAsync: function(req,res,serverResData,callback)的方法,这个方法就是负责对anyproxy拿到的数据进行各种操作。一开始应该只有callback(serverResData);这条语句的意思是直接返回服务器响应数据给客户端。直接删掉这条语句,替换成大牛写的如下代码。这里的代码我并没有做什么改动,里面的注释也解释的给非常清楚,直接按逻辑看懂就行,问题不大。

replaceServerResDataAsync: function(req,res,serverResData,callback){

//console.log("开始第一种页面爬取");

if(serverResData.toString() !== ""){

6 try {//防止报错退出程序

var reg = /msgList = (.*?);/;//定义历史消息正则匹配规则

var ret = reg.exec(serverResData.toString());//转换变量为string

HttpPost(ret[1],req.url,"/InternetSpider/getData/showBiz");//这个函数是后文定义的,将匹配到的历史消息json发送到自己的服务器

var http = require('http');

http.get('http://xxx/getWxHis', function(res) {//这个地址是自己服务器上的一个程序,目的是为了获取到下一个链接地址,将地址放在一个js脚本中,将页面自动跳转到下一页。后文将介绍getWxHis.php的原理。

res.on('data', function(chunk){

callback(chunk+serverResData);//将返回的代码插入到历史消息页面中,并返回显示出来

})

});

//console.log("开始第一种页面爬取向下翻形式");

try {

var json = JSON.parse(serverResData.toString());

if (json.general_msg_list != []) {

HttpPost(json.general_msg_list,req.url,"/xxx/showBiz");//这个函数和上面的一样是后文定义的,将第二页历史消息的json发送到自己的服务器

}

}catch(e){

console.log(e);//错误捕捉

}

callback(serverResData);//直接返回第二页json内容

}

}

//console.log("开始第一种页面爬取 结束");

try {

var reg = /var msgList = \'(.*?)\';/;//定义历史消息正则匹配规则(和第一种页面形式的正则不同)

var ret = reg.exec(serverResData.toString());//转换变量为string

HttpPost(ret[1],req.url,"/xxx/showBiz");//这个函数是后文定义的,将匹配到的历史消息json发送到自己的服务器

var http = require('http');

http.get('xxx/getWxHis', function(res) {//这个地址是自己服务器上的一个程序,目的是为了获取到下一个链接地址,将地址放在一个js脚本中,将页面自动跳转到下一页。后文将介绍getWxHis.php的原理。

res.on('data', function(chunk){

callback(chunk+serverResData);//将返回的代码插入到历史消息页面中,并返回显示出来

})

});

}catch(e){

//console.log(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,"/xxx/showBiz");//这个函数和上面的一样是后文定义的,将第二页历史消息的json发送到自己的服务器

}

}catch(e){

console.log(e);

}

callback(serverResData);

try {

HttpPost(serverResData,req.url,"/xxx/getMsgExt");//函数是后文定义的,功能是将文章阅读量点赞量的json发送到服务器

}catch(e){

}

callback(serverResData);

try {

var http = require('http');

http.get('http://xxx/getWxPost', function(res) {//这个地址是自己服务器上的另一个程序,目的是为了获取到下一个链接地址,将地址放在一个js脚本中,将页面自动跳转到下一页。后文将介绍getWxPost.php的原理。

res.on('data', function(chunk){

callback(chunk+serverResData);

})

});

}catch(e){

callback(serverResData);

}

}else{

callback(serverResData);

}

//callback(serverResData);

},

下图是上文中的HttpPost方法内容。

function HttpPost(str,url,path) {//将json发送到服务器,str为json内容,url为历史消息页面地址,path是接收程序的路径和文件名     console.log("开始执行转发操作");     try{     var http = require('http');     var data = {         str: encodeURIComponent(str),         url: encodeURIComponent(url)     };     data = require('querystring').stringify(data);     var options = {         method: "POST",         host: "xxx",//注意没有http://,这是服务器的域名。         port: xxx,         path: path,//接收程序的路径和文件名         headers: {             'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',             "Content-Length": data.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(data);     req.end();     }catch(e){         console.log("错误信息:"+e);     }     console.log("转发操作结束"); }

我是用java写的服务端代码。

public String getWxPost() {

// TODO Auto-generated method stub

/**

* 首先删除采集队列表中load=1的行

* 然后从队列表中按照“order by id asc”选择多行(注意这一行和上面的程序不一样)

*/

tmpListMapper.deleteByLoad(1);

List queues = tmpListMapper.selectMany(5);

String url = "";

if(queues != null && queues.size() != 0 && queues.size() > 1){

TmpList queue = queues.get(0);

url = queue.getContentUrl();

queue.setIsload(1);

int result = tmpListMapper.updateByPrimaryKey(queue);

System.out.println("update result:"+result);

}else{

System.out.println("getpost queues is null?"+queues==null?null:queues.size());

WeiXin weiXin = weiXinMapper.selectOne();

String biz = weiXin.getBiz();

if((Math.random()>0.5?1:0) == 1){

url = "http://mp.weixin.qq.com/mp/getmasssendmsg?__biz=" + biz +

}else{

url = "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=" + biz +

}

url = "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=" + biz +

weiXin.setCollect(System.currentTimeMillis());

int result = weiXinMapper.updateByPrimaryKey(weiXin);

System.out.println("getPost weiXin updateResult:"+result);

}

int randomTime = new Random().nextInt(3) + 3;

String jsCode = "";

return jsCode;

}

public void getMsgExt(String str,String url) {

// TODO Auto-generated method stub

String biz = "";

String sn = "";

Map queryStrs = HttpUrlParser.parseUrl(url);

if(queryStrs != null){

biz = queryStrs.get("__biz");

biz = biz + "==";

sn = queryStrs.get("sn");

sn = "%" + sn + "%";

}

/**

* $sql = "select * from `文章表` where `biz`='".$biz."'

* and `content_url` like '%".$sn."%'" limit 0,1;

* 根据biz和sn找到对应的文章

*/

Post post = postMapper.selectByBizAndSn(biz, sn);

if(post == null){

System.out.println("biz:"+biz);

System.out.println("sn:"+sn);

tmpListMapper.deleteByLoad(1);

return;

}

// System.out.println("json数据:"+str);

Integer read_num;

Integer like_num;

try{

read_num = JsonPath.read(str, "['appmsgstat']['read_num']");//阅读量

like_num = JsonPath.read(str, "['appmsgstat']['like_num']");//点赞量

}catch(Exception e){

read_num = 123;//阅读量

like_num = 321;//点赞量

System.out.println("read_num:"+read_num);

System.out.println("like_num:"+like_num);

System.out.println(e.getMessage());

}

/**

* 在这里同样根据sn在采集队列表中删除对应的文章,代表这篇文章可以移出采集队列了

* $sql = "delete from `队列表` where `content_url` like '%".$sn."%'"

*/

tmpListMapper.deleteBySn(sn);

//然后将阅读量和点赞量更新到文章表中。

post.setReadnum(read_num);

post.setLikenum(like_num);

postMapper.updateByPrimaryKey(post);

}

处理跳转向微信注入js的方法:

public String getWxHis() {

String url = "";

// TODO Auto-generated method stub

/**

* 在采集队列表中有一个load字段,当值等于1时代表正在被读取

* 首先删除采集队列表中load=1的行

* 然后从队列表中任意select一行

*/

tmpListMapper.deleteByLoad(1);

TmpList queue = tmpListMapper.selectRandomOne();

System.out.println("queue is null?"+queue);

if(queue == null){//队列表为空

/**

*/

WeiXin weiXin = weiXinMapper.selectOne();

String biz = weiXin.getBiz();

url = "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=" + biz +

weiXin.setCollect(System.currentTimeMillis());

int result = weiXinMapper.updateByPrimaryKey(weiXin);

System.out.println("getHis weiXin updateResult:"+result);

}else{

//取得当前这一行的content_url字段

url = queue.getContentUrl();

//将load字段update为1

tmpListMapper.updateByContentUrl(url);

}

//将下一个将要跳转的$url变成js脚本,由anyproxy注入到微信页面中。

//echo "";

int randomTime = new Random().nextInt(3) + 3;

String jsCode = "";

return jsCode;

}

我是用webmagic写的爬虫,轻量好用。

public class SpiderModel implements PageProcessor{

private static PostMapper postMapper;

private static List posts;

// 抓取网站的相关配置,包括编码、抓取间隔、重试次数等

private Site site = Site.me().setRetryTimes(3).setSleepTime(100);

public Site getSite() {

// TODO Auto-generated method stub

return this.site;

}

public void process(Page page) {

// TODO Auto-generated method stub

Post post = posts.remove(0);

String content = page.getHtml().xpath("//div[@id='js_content']").get();

//存在和谐文章 此处做判定如果有直接删除记录或设置表示位表示文章被和谐

if(content == null){

System.out.println("文章已和谐!");

//postMapper.deleteByPrimaryKey(post.getId());

return;

}

String contentSnap = content.replaceAll("data-src", "src").replaceAll("preview.html", "player.html");//快照

String contentTxt = HtmlToWord.stripHtml(content);//纯文本内容

Selectable metaContent = page.getHtml().xpath("//div[@id='meta_content']");

String pubTime = null;

String wxname = null;

String author = null;

if(metaContent != null){

pubTime = metaContent.xpath("//em[@id='post-date']").get();

if(pubTime != null){

pubTime = HtmlToWord.stripHtml(pubTime);//文章发布时间

}

wxname = metaContent.xpath("//a[@id='post-user']").get();

if(wxname != null){

}

author = metaContent.xpath("//em[@class='rich_media_meta rich_media_meta_text' and @id!='post-date']").get();

if(author != null){

}

}

// System.out.println("发布时间:"+pubTime);

String title = post.getTitle().replaceAll(" ", "");//文章标题

String digest = post.getDigest();//文章摘要

int likeNum = post.getLikenum();//文章点赞数

int readNum = post.getReadnum();//文章阅读数

String contentUrl = post.getContentUrl();//文章链接

WechatInfoBean wechatBean = new WechatInfoBean();

wechatBean.setTitle(title);

wechatBean.setContent(contentTxt);//纯文本内容

wechatBean.setSourceCode(contentSnap);//快照

wechatBean.setLikeCount(likeNum);

wechatBean.setViewCount(readNum);

wechatBean.setAbstractText(digest);//摘要

wechatBean.setUrl(contentUrl);

wechatBean.setPublishTime(pubTime);

wechatBean.setAuthor(author);

WechatStorage.saveWechatInfo(wechatBean);

//标示文章已经被爬取

post.setIsSpider(1);

postMapper.updateByPrimaryKey(post);

}

public static void startSpider(List inposts,PostMapper myPostMapper,String... urls){

long startTime, endTime;

startTime = System.currentTimeMillis();

postMapper = myPostMapper;

posts = inposts;

HttpClientDownloader httpClientDownloader = new HttpClientDownloader();

SpiderModel spiderModel = new SpiderModel();

Spider mySpider = Spider.create(spiderModel).addUrl(urls);

mySpider.setDownloader(httpClientDownloader);

try {

SpiderMonitor.instance().register(mySpider);

mySpider.thread(1).run();

} catch (JMException e) {

e.printStackTrace();

}

endTime = System.currentTimeMillis();

System.out.println("爬取时间" + ((endTime - startTime) / 1000) + "秒--");

}

}

其它的一些无关逻辑的存储数据代码就不贴了,这里我把代理服务器抓取到的数据存在了mysql,把自己的爬虫程序爬到的数据存储在了mongodb。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:详解eclipse中Maven工程使用Tomcat7以上插件的方法
下一篇:api接口文档有什么作用(api接口使用)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~