使用fiddler自动化抓取微信公众号文章的点赞与阅读数

本文章为lonter首创,只发布在csdn平台,严禁转载
这几天接到任务,需要开发一个微信榜单的功能,因此需要采集微信公众号文章的阅读数,点赞数和评论数,榜单内的微信公众号有一百多个,每个月出一次榜单。
接到这个任务,我开始研究如何抓取微信阅读数,点赞数和评论数,通过大量参考网上的技术文章,最终确定了我所使用的方案:使用Fiddler进行采集
本文章为lonter首创,只发布在csdn平台,严禁转载
第一步:设置Fiddler
这里写图片描述
如图设置,此处为设置Fiddler支持https

本文章为lonter首创,只发布在csdn平台,严禁转载
第二步:设置Fiddler脚本
Fiddler工具打开后,选择Rules ->Customize Rules打开Fiddler ScriptEditor编辑器,编辑器如下:
这里写图片描述
这里我们只需要了解OnBeforeResponse方法,本方法为在http请求返回给客户端之前执行的方法,我们主要在本方法内进行脚本的编写

本文章为lonter首创,只发布在csdn平台,严禁转载
第三步:选择性截取responsebody存储到文本中
研究各个请求,找到返回点赞数与评论的请求,具体请求如图:
这里写图片描述
然后开始在Fiddler ScriptEditor的方法中编写具体的存储脚本:

// 首先判断请求域名是否是自己感兴趣的,以及URL中是否含有自己感兴趣的特征字符串。如果是,则将该请求的URL和QueryString记录到日志文件 "c:/fiddler-token.log"中。  
        if (oSession.HostnameIs("mp.weixin.qq.com") && oSession.uriContains("https://mp.weixin.qq.com/mp/getappmsgext")){  
            var filename = "C:/fiddler-token.log";  
            var curDate = new Date();  
            var logContent =  "[" + curDate.toLocaleString() + "] " + oSession.PathAndQuery + "\r\n"+oSession.GetResponseBodyAsString()+"\r\n";  
            var sw : System.IO.StreamWriter;  
            if (System.IO.File.Exists(filename)){  
                sw = System.IO.File.AppendText(filename);  
                sw.Write(logContent);  
            }  
            else{  
                sw = System.IO.File.CreateText(filename);  
                sw.Write(logContent);  
            }  
            sw.Close();  
            sw.Dispose();  
        }

本代码功能为将涉及阅读数点赞数的数据存储到文本中,结果如图:
这里写图片描述

本文章为lonter首创,只发布在csdn平台,严禁转载
第四步:篡改公众号文章页面的js代码,让页面自动按照你的意思跳转
由于本功能可能涉及灰色地带,so,声明一下,不要用来干坏事!!!
我们先来看看公众号文章的主页面:
这里写图片描述
很明显,每段js脚本都是以 script nonce=”1007993124” 开头,而nonce字段的作用是防止xxs的,如果js的nonce与原来的不符,js是不会被执行的,因此,需要在脚本编写上费点功夫,具体的逻辑代码如图:
这里写图片描述

这段js加载后,保存一下Fiddler ScriptEditor,然后你点击微信公众号文章,你回在Fiddler中看到如下:
这里写图片描述

然后,你回发现页面会自动的跳转

本文章为lonter首创,只发布在csdn平台,严禁转载
第五步:开发任务获取页面
我们需要开发一个微信的中转页面,这个页面会从后台获取一篇微信公众号文章,然后让微信浏览器打开
具体html如下:

<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="./js/hm.js"></script>
<script src="./js/jquery-3.2.1.min.js"></script>
<script language="javascript" >   
window.onload=function(){
    nextdoor();
}
function nextdoor(){
    var taskid=GetQueryString("taskid")
    var ob={task:taskid};
    $.ajax({
      type: "POST",
      url: "rest/wxCrawler/wxTask",
      contentType: "application/json; charset=utf-8",
      data: JSON.stringify(ob),
      dataType: "json",
      success: function (message) {
          var url=message.url;
          var taskid=message.task;//每个微信客户端的id,这个id应该在后端自动生成
          if(url==("http://127.0.0.1:8080/Externalservice/test.html?taskid="+taskid))
          {
              setTimeout(function(){window.location="http://127.0.0.1:8080/Externalservice/test.html?taskid="+taskid;},10000);
          }else
          {
              //alert(url+"&taskid="+taskid);
              window.location=url+"&taskid="+taskid+"#rd";  
          }

       },
      error: function (message) {
         alert("提交数据失败");
      }
  });
}

function GetQueryString(name)
{
     var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
     var r = window.location.search.substr(1).match(reg);
     if(r!=null)return  unescape(r[2]); return null;
}
</script> 
<div align="center">
<p>阅读刷新中转页面,页面正在跳转中...</p>
<p>如一直刷新本页面,则一直等待后台分配任务</p>
</div>

</body>
</html>

至于后端接口,想必很多人都能写吧,我就只搞一部分出来:

package test.springmvc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.mangofactory.swagger.plugin.EnableSwagger;
import com.wordnik.swagger.annotations.ApiOperation;

import net.sf.json.JSONObject;
import test.springmvc.Artmodel.WxTask;
import test.springmvc.redis.JedisUtil;


/**
 * 
 * @author Administrator
 *
 */
@Controller
@EnableSwagger
@RequestMapping("/wxCrawler")
public class TopController {
    private final static Logger logger = LoggerFactory.getLogger(TopController.class);
    JedisUtil ju=new JedisUtil();
    @ApiOperation(value = "微信任务调度接口", notes = "notes", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @RequestMapping(value = "wxTask", method = RequestMethod.POST)
    @ResponseBody
    // 使用了@RequestBody,不能在拦截器中,获得流中的数据,再json转换,拦截器中,也不清楚数据的类型,无法转换成java对象
    // 只能手动调用方法
    public String WeixinTask(@RequestBody WxTask wt) {
        String task=wt.getTask();
        byte[] redisKey= task.getBytes();//队列名称
        byte[] bys=ju.rpop(redisKey);
        if(bys==null)
        {
            JSONObject json=new JSONObject();
            json.put("url", "http://127.0.0.1:8080/Externalservice/test.html?taskid="+task);
            json.put("task", task);
            return json.toString();
        }else
        {
            String info=new String(bys);
            JSONObject json=JSONObject.fromObject(info);
            String url=json.getString("url");
            url=url.replace("#rd", "");
            json.put("url", url);
            json.put("task", task);
            return json.toString();
        }

    }

}

这段java和js的主要特点是可以多任务的进行分布式抓取,到这里,已经完成了所有的开发

你只需要写入几百几千的公众号文章链接,然后用微信打开http://localhost:8080/Externalservice/test.html?taskid=xxxxxl类似这样的中转页,你就会发现微信浏览器不停的跳转

本文章为lonter首创,只发布在csdn平台,严禁转载
第六步:解析Fiddler存储下来的文本

package com.crawler.top;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import com.mysql.jdbc.UpdatableResultSet;
import com.util.DBUtil;

import net.sf.json.JSONObject;


/**
 * 读取Fiddler写入的内容,并将结果写入数据库
 * @author Administrator
 *
 */
public class ReaderTxt {
    DBUtil dbu=new DBUtil();
    public static void main(String[] args)
    {
        ReaderTxt rt=new ReaderTxt();
        ArrayList<String> list=rt.InitTxt();
        for(int i=0;i<list.size();i+=2)
        {
            String urlmsg=list.get(i);
            int start=urlmsg.indexOf("&sn=")+4;
            urlmsg=urlmsg.substring(start);
            int end=urlmsg.indexOf("&");
            urlmsg=urlmsg.substring(0, end);
            String info=list.get(i+1);
            JSONObject json=JSONObject.fromObject(info);
            if(json.has("appmsgstat"))
            {
                JSONObject appmsgstat=json.getJSONObject("appmsgstat");
                int read_num=appmsgstat.getInt("read_num");
                int like_num=appmsgstat.getInt("like_num");
                rt.updata(urlmsg, read_num, like_num);
            }

        }
        rt.dbu.destroy();
    }
    /**
     * 更新数据库中的文章数据
     * @param urlmsg
     * @param read_num
     * @param like_num
     */
    public void updata(String urlmsg,int read_num,int like_num)
    {
        String sql="update task_info set readers="+read_num+", attitudes="+like_num+" where url like '%"+urlmsg+"%'";
        try {
            dbu.Update(sql);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public ArrayList<String> InitTxt()
    {
        ArrayList<String> list=new ArrayList<String>();
         try { // 防止文件建立或读取失败,用catch捕捉错误并打印,也可以throw  

            /* 读入TXT文件 */  
            String pathname = "C:\\fiddler-token.log"; // 绝对路径或相对路径都可以,这里是绝对路径,写入文件时演示相对路径  
            File filename = new File(pathname);
            InputStreamReader reader = new InputStreamReader(  
                    new FileInputStream(filename),"utf-8"); // 建立一个输入流对象reader  
            BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言  
            String line = "";  
            while (line != null) {  
                line = br.readLine(); // 一次读入一行数据  
               if(line==null)
               { 
                   break;
               }
               list.add(line);
            }  
         } catch (Exception e) {  
            e.printStackTrace();  
        } 
         return list;
    }
}

这个挺简单的,嘿嘿

好啦,搞定啦
我的爬虫交流群:142351055

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值