吴怖卫---第二次作业

这个作业属于哪个课程 <至诚软工实践F班>
这个作业要求在哪里 作业要求
这个作业的目标 <学习Fiddler,抓取数据包,进行数据分析,获取所需要的数据>
Github 地址 https://github.com/563433225/212106736

使用到的软件:

①谷歌浏览器

②Fiddler

③IDEA编译器

参考信息网:B站

使用语言:Java

jar包添加网:mvnrepository

JSON在线解析网:JSON在线视图查看器


任务一:使用 fiddler 抓包工具+代码,实时监控朴朴上某产品的详细价格信息


解题思路:

本次作业用到Fiddler,微信小程序,一开始使用模拟器,但一直无法正常在模拟器和备用手机上使用朴朴软件,最终选择微信小程序朴朴进行操作。

首先在选定监听的朴朴商品页面,在使用Fiddler进行数据抓取。获取到朴朴页面有js文件进行传输,获取的js问价的呢get请求地址,添加协议头,获取内容,再通过json在线视图查看器,查看所欲内yi容所在节点下,获取到指定节点后,一节节往下,到达所需要到达的节点,在通过节点内的Key值,通过方法获取指定Key值对应的Value,然后将数据进行搭配输出。


①抓取数据

此截图为需要抓取数据的朴朴商品截图

Fiddler数据抓取截图

②数据分析

朴朴中我们所需要的数据在data节点下,每个所需要的资源,已在图片上打上备注


③代码解析

本次抓包代码使用的语言是 Java

1.连接朴朴,获取js文件
//连接方法
    private static String getDocument( String sUrl) throws Exception {
        //创建HttpClient对象,打开浏览器
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //发起Gget请求,输入网址
        HttpGet httpGet = new HttpGet(sUrl);
        //添加协议头
        httpGet.addHeader("Host","j1.pupuapi.com\n");
        httpGet.addHeader("Connection","keep-alive");
        httpGet.addHeader("Accep","application/json");
        httpGet.addHeader("Authorization","Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIiLCJhdWQiOiJodHRwczovL3VjLnB1cHVhcGkuY29tIiwiaXNfbm90X25vdmljZSI6IjEiLCJpc3MiOiJodHRwczovL3VjLnB1cHVhcGkuY29tIiwiZ2l2ZW5fbmFtZSI6IuWNq-WNq-WTnyIsImV4cCI6MTY0NzU5NjMzMywidmVyc2lvbiI6IjIuMCIsImp0aSI6IjM2ZmM4NDRmLWI1MDctNGQwNi05MDEzLWQxZGUxYzYwYTMwYiJ9.QGA4veRF5F7vpNXtGjnFL1vg2w17KWLP90D6OyoUImI");
        httpGet.addHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat");
        httpGet.addHeader("content-type",":application/json");
        httpGet.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36");
        httpGet.addHeader("open-id","oMwzt0N-TOFXilsZAEJo3hOq6MtM");
        httpGet.addHeader("pp-os"," 0");
        httpGet.addHeader("pp-placeid","8eb75536-f871-452a-a3a8-37a3611eed13");
        httpGet.addHeader("pp-userid","36fc844f-b507-4d06-9013-d1de1c60a30b");
        httpGet.addHeader("pp-version:","2021063100");
        httpGet.addHeader("pp_storeid","7f10e39a-57cb-41a6-94f2-d5bf4e2abbbc");
        httpGet.addHeader("Referer","https://servicewechat.com/wx122ef876a7132eb4/156/page-frame.html");
        //发其请求,返回响应数值,200为响应成功,使用httpClient对象发其请求
        response = httpClient.execute(httpGet);
        if (response.getStatusLine().getStatusCode()==200){
            HttpEntity httpEntity = response.getEntity();
            String content = EntityUtils.toString(httpEntity);
            return  content;
        }
        return null;
    }
2.上半部分的代码
private static void top() throws Exception {
        //使用连接方法
        String dom = getDocument(pupu);
        //System.out.println(dom);
        //将放回的字符串转换为json
        JSONObject jsonObject = new JSONObject(dom);
        //按节点查找
        JSONObject data = jsonObject.getJSONObject("data");

        //获取name的value
        String name =data.getString("name");

        //当前价格
        double price = data.getDouble("price")/100;

        //原价
        double market_price = data.getDouble("market_price")/100;

        //规格
        String spec= data.getString("spec");

        //内容详情
        String share_content = data.getString("share_content");
        System.out.println("---------------"+name+"---------------");
        System.out.println("规格:"+spec);
        System.out.println("价格:"+price);
        System.out.println("原价/折扣价:"+market_price+"/"+price);
        System.out.println("详细内容:"+share_content);
    }

3.分隔线代码
    private static void centile() throws Exception {
        //使用连接方法
        String dom = getDocument(pupu);
        //将放回的字符串转换为json
        JSONObject jsonObject = new JSONObject(dom);
        //按节点查找
        JSONObject data = jsonObject.getJSONObject("data");
        //获取name的value
        String name =data.getString("name");
        System.out.println("---------------\""+name+"\"的价格波动---------------");
    }
4.实时监听代码
    private static void monitor() {
        new Timer().schedule(new TimerTask() {
            //执行监听次数
            private int count = 10;
            @Override
            public void run() {
                try {
                    if (count>0){
                        //使用连接方法
                        String dom = getDocument(pupu);
                        //将放回的字符串转换为json
                        JSONObject jsonObject = new JSONObject(dom);
                        //按节点查找
                        JSONObject data = jsonObject.getJSONObject("data");
                        //获取name的value
                        String name =data.getString("name");
                        //当前价格
                        double price = data.getDouble("price")/100;
                        //当前系统时间
                        String date = String.format("%tF %1$tT ",LocalDateTime.now());
                        System.out.println("当前时间为:"+date+"   【"+name+"】的价格为:"+price);
                        //执行过后减少一次
                        count--;
                    }
                    else {
                        //停止监听
                        cancel();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },0,2000);//启动延时为0,每隔2秒执行一次
    }
5.主方法main()
    private static CloseableHttpResponse response = null;
    private static String pupu = "https://j1.pupuapi.com/client/product/storeproduct/detail/7f10e39a-57cb-41a6-94f2-d5bf4e2abbbc/ed60af11-25b0-48b8-bc5b-f9136d9f89ad";

    public static void main(String[] args) throws Exception {
        //头代码
        top();
        System.out.println();
        //第二行标题
        centile();
        //实时监听方法
        monitor();
    }

④结果截图


任务二:爬取自己的知乎收藏夹,以每个收藏夹的名称为大类,其下展示各个具体收藏文章的名称及其链接


解题思路:

首先拥有知乎账号,并且按要求完成收藏夹内容。

通过Fiddler工具获取到知乎的网页请求连接和协议头,通过html页面发现,所有的文件内容所在位置都一致,所以首先通过html页面获取到 a 标签内的内容以及所对应的链接。通过链接访问子文件夹下的数据,进行获取。


①抓取数据

首先获取html上的标签,按 标签的 class 查找

每个收藏夹下的文件js数据


②数据分析

通过Fiddler获取的js文件,通过视图解析,获取到所在位置


③代码解析

1.Test类---主类
public static void main(String[] args) throws Exception {
        //getDocument()访问方法
        Document doc = getDocument("https://www.zhihu.com/people/wei-wei-59-66-16/collections");
        //获取标题
        String title = doc.getElementsByTag("title").first().text();
        System.out.println(title);
        //根据class获取到 页面元素内容
        Elements tables1 = doc.getElementsByClass("SelfCollectionItem-title");
        //System.out.println(tables1);
        //根据  a  标签来划分
        Elements a = tables1.select("a");
        String str ="[{";
        for(int j=0;j<a.size();j++) {
            System.out.println("");
            //获取到标签中的内容
            String text = a.get(j).text();
            System.out.println("收藏夹名称:    "+text);
            //获取A标签的href 网址  select 获取到当前A标签 attr href 获取到地址
            String s = a.get(j).select("a").attr("href");
            //正则表达式,获取网页最后的数字id   添加trim防止两端有空格
            //id:为该收藏夹的ID编码
            String id = Pattern.compile("[^0-9]").matcher(s).replaceAll("").trim();
            //System.out.println(id.trim());"{\"title\":\""+title+"\",\"url\":\""+url+"\"},";
            
            //下面的Jsonsj.geturl()为Jsonjs类的geturl()方法,用于实现每个收藏夹下的子文件查找
            //id:为该收藏夹的ID编码
            str = str +"\"favorites\":\""+text+"\","+Jsonsj.geturl("https://www.zhihu.com/api/v4/collections/"+id+"/items?offset=0&limit=20")+",";
        }
        str = str.substring(0,str.length() - 1);
        str = str+"}]";
        System.out.println("本次数据的JSON格式:"+str);
    }
2.Test类的连接方法
private static Document getDocument( String sUrl) throws IOException {
    //访问的url点至,第二个是超时时间
    Document doc2 = null;
    //创建网站连接
    Connection connect = Jsoup.connect(sUrl);
    //添加协议头
    connect.header("Host","www.zhihu.com");
    connect.header("Connection","keep-alive");
    connect.header("Cache-Control","max-age=0");
    connect.header("sec-ch-ua"," \" Not A;Brand\";v=\"99\", \"Chromium\";v=\"99\", \"Google Chrome\";v=\"99\"");
    connect.header("sec-ch-ua-mobile","?0");
    connect.header("sec-ch-ua-platform","\"Windows\"");
    connect.header("Upgrade-Insecure-Requests","1");
    connect.header("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36");
    connect.header("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
    connect.header("Sec-Fetch-Site","same-origin");
    connect.header("Sec-Fetch-Mode","navigate");
    connect.header("Sec-Fetch-User","?1");
    connect.header("Fetch-Dest","document");
    //连接网址
    doc2 = connect.get();
    return doc2;
}
3.Jsonsj类
 private static CloseableHttpResponse response = null;;
    //通过JSON获取所需要的信息
    public static String geturl(String url) throws Exception {
        String str = "";
        String s = extracted(url);
    //将获取的字符串存储到json中
    JSONObject jsonResult  = new JSONObject(s);
       // System.out.println(jsonResult);
    //这是json数组,所以用到JSONArray
    JSONArray json1 = jsonResult.getJSONArray("data");
        //System.out.println(json1);
        //System.out.println(json1);
        for (int i = 0; i < json1.length(); i++) {
            //按节点查找
        JSONObject jo1 = json1.getJSONObject(i);
        JSONObject jo2 = jo1.getJSONObject("content");
        JSONObject jo3 =jo2.getJSONObject("question");
        String title = jo3.getString("title");
        String utl = jo3.getString("url");
        System.out.println(title);
        System.out.println(utl);
        str= str+"{\"title\":\""+title+"\",\"url\":\""+url+"\"},";
        }
        str = str.substring(0,str.length() - 1);
        str = "\"count\":["+str+"]";
        return str;
}
4.Jsonsj类的连接方法
//连接方法
private static  String extracted( String us) throws Exception {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    //输入网址,发起get请求,创建HttpGet对象
    HttpGet httpGet = new HttpGet(us);
    response = httpClient.execute(httpGet);
    try{
        //响应代码为200,则链接成功
        if (response.getStatusLine().getStatusCode() == 200) {
            //解析响应,获取数据
            HttpEntity httpEntity = response.getEntity();
            String s = EntityUtils.toString(httpEntity);
            return s;
        }else {
            System.out.println("连接失败");
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ParseException e) {
        e.printStackTrace();
    }finally {
        //关闭连接
        response.close();
    }
    return null;
}

④结果截图


GitHub提交


问题,总结及反思


本次作业使用的一切可以说是完全新的一个知识,从来没有接触过这类的学习,在大家选择python完成作业时,我还是选择使用Java,都说使用python会快,但我觉得大家都写一样的话,那就没意思了,虽然Java在编写的过程中会困难很多,但只要努力学习,查阅资料的话,也可以完成,本次作业的学习耗时四天时间,在这四天中学习了很多新的知识。

从刚开始朴朴连接访问的时候,访问的方式使用了两三种,试了很多次,最后获取网站的json数据也耗费了许多时间。

在知乎任务中,投机取巧先从html中,通过class来锁定所欲要的a标签的文本内容和href链接,在访问文件下的时候出现了问题,比如获取的href链接为 /question/265088955 ,我就直接在前面加上http://www.zhihua,com ,合并在一起访问,以为结束的时,却发现访问不出我需要的数据,每个这样合在一起使用访问的链接,全部都指向一了一个地址 https://www.zhihu.com/people/undefined ,在这时我陷入了死循环,在我问过舍友后才了解到,获取到的href链接没错,,但是返回的数据是js文件数据,我这是恍然大悟,再次通过Fiddler软件找到了所欲要的js文件,通过对比,每个收藏夹之间请求的get链接只有id不一样,所以截取到id,放入指定的链接格式,便可以使用了。

知乎任务的代码中还是存在问题,有的子文件可能是评论,无法获取内容,在这我需要在继续学习,要将所有在收藏夹下的都读取出来。

posted @ 2022-03-18 18:40  卫卫是我  阅读(71)  评论(0编辑  收藏  举报