zoukankan      html  css  js  c++  java
  • 自动评论csdn博客文章实现

    正文

    我们来用java代码爬取csdn博客网站,然后自动评论,这一波操作可以说是相当风骚了,话不多说,咱上代码。

    第一步是登录代码,这个网上一大把,代码中用到了jsoup依赖包,用于解析html获取相应元素,相当于css选择器,很强大的三方件。

    /**
      * 登录csdn页面,评论当然需要登录了
      * 
      * @throws Exception
      */
     public static void loginCsdnPager() throws Exception {
       String html = HttpUtils.sendGet("https://passport.csdn.net/account/login?ref=toolbar");
    
       try {
         Thread.currentThread().sleep(3000);
       } catch (InterruptedException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
       }
       Document doc = Jsoup.parse(html);
    
       Element form = doc.select(".user-pass").get(0);
       String lt = form.select("input[name=lt]").get(0).val();
       String execution = form.select("input[name=execution]").get(0).val();
       String _eventId = form.select("input[name=_eventId]").get(0).val();
    
       List<NameValuePair> nvps = new ArrayList<NameValuePair>();
       nvps.add(new BasicNameValuePair("username", CSDNACCOUNT));
       nvps.add(new BasicNameValuePair("password", CSDNPASSWORD));
       nvps.add(new BasicNameValuePair("lt", lt));
       nvps.add(new BasicNameValuePair("execution", execution));
       nvps.add(new BasicNameValuePair("_eventId", _eventId));
    
       System.out.println(nvps);
       // 开始请求CSDN服务器进行登录操作。一个简单封装,直接获取返回结果
       String ret = HttpUtils.sendPost("https://passport.csdn.net/account/login", nvps);
    
       System.out.println("ret is " + ret);
       // ret中会包含以下信息,进行判断即可。
       if (ret.indexOf("redirect_back") > -1) {
         System.out.println("登陆成功。。。。。");
       } else if (ret.indexOf("登录太频繁") > -1) {
         throw new Exception("登录太频繁,请稍后再试。。。。。");
       } else {
         throw new Exception("登录太频繁,请稍后再试。。。。。");
       }
     }
    

    有了登录代码我们还得获取博客文章列表,这是我们爬取的源头。下面以博客首页为起点往其他网络节点爬:

    https://blog.csdn.net

    我们可以把自己当做一个虫子,接下来将在蜘蛛网上从A节点到B节点,一直爬到目的地。

    首先进入首页,然后获取到首页左侧栏的分类列表的url,点开这些url,就是分类下的所有文章了。这里我们只取每个分类下初始页的文章列表url(当然还可以自行实现鼠标下拉时的分页,以获取到更多的文章列表),这里定义了一个名为FETCHPAGES的数组常量,管理所需爬取的分类列表。

    
    String html = HttpUtils.sendGet("https://blog.csdn.net/");
    
       Document doc = Jsoup.parse(html);
       Elements as = doc.select(".nav_com").select("li").select("a");
    
       // 收集文章a标签
       List<Elements> blogList = Lists.newArrayListWithCapacity(as.size());
       for (Element a : as) {
    
         if (!FETCHPAGES.contains(a.text())) {
           continue;
         }
    
         String fetcheUrl = "https://blog.csdn.net" + a.attr("href");
         System.out.println(fetcheUrl);
         String blogHtml = HttpUtils.sendGet(fetcheUrl);
    
         Document blogDoc = Jsoup.parse(blogHtml);
    
         Elements blogAs = blogDoc.select(".title").select("h2").select("a");
    
         System.out.println(blogAs);
         blogList.add(blogAs);
       }
    

    收集好文章列表之后,我们就需要登录了(登录后收集列表会出问题,具体原因不明),这里登录只是接下来评论时必须。

    // 收集完a标签后再登陆,否则会丢掉很多a标签,具体原因不名
       loginCsdnPager();
    
       BufferedOutputStream bos = null;
       // 评论成功计数器
       int count = 0;
       try {
         // 将评论成功的url打印到文件里
         File file = new File("D:/tmp/successLog/success.log");
         bos = new BufferedOutputStream(new FileOutputStream(file));
         // 爬取所有a标签
         for (Elements blogs : blogList) {
    
           for (Element blog : blogs) {
    
             // 拿到文章url
             String href = blog.attr("href");
    
             // 获取文章url后的ID,在评论时需要用到
             String commitSuffixUrl = href.substring(href.lastIndexOf("/") + 1);
    
             // 打开文章
             String blogHtml = HttpUtils.sendGet(href);
             System.out.println(blog.text() + "------------" + blog.attr("href"));
    
             Document blogDoc = Jsoup.parse(blogHtml);
             Elements titleAs = blogDoc.select(".title-box").select("a");
    
             System.out.println(titleAs);
    
             if (titleAs != null && !titleAs.isEmpty()) {
               // 评论请求url前缀
               String commitPrefixUrl = titleAs.get(0).attr("href");
               //
               System.out.println(titleAs.text() + "-----------" + commitPrefixUrl);
    
               // 拼接评论请求url
               String commitUrl = commitPrefixUrl + "/phoenix/comment/submit?id=" + commitSuffixUrl;
    
               System.out.println("commitUrl ==" + commitUrl);
    
               // 构造评论请求所需body体
               List<NameValuePair> nvps = new ArrayList<NameValuePair>();
               nvps.add(new BasicNameValuePair("replyId", ""));
               nvps.add(new BasicNameValuePair("content",
                   "加Wei信ammlysouw 免费领取java、python、前端、安卓、数据库、大数据、IOS等学习资料"));
    
               // 发起评论
               String postRequest = HttpUtils.sendPost(commitUrl, nvps);
               JSONObject jsonObj = JSONObject.parseObject(postRequest);
    
               System.out.println(postRequest);
    
               // 评论结果,成功为1
               if (jsonObj.getInteger("result") == 1) {
    
                 String articalUrl = commitPrefixUrl + "/article/details/" + commitSuffixUrl + "
    ";
                 System.out.println("success articalUrl is " + articalUrl);
                 // 将评论成功的url记录到文件
                 bos.write(articalUrl.getBytes());
                 bos.flush();
                 count++;
               } else {
                 // 不成功说明请求太快,线程休眠2秒,这里会丢掉评论失败的文章
                 try {
                   Thread.currentThread().sleep(2 * 60 * 1000);
                 } catch (InterruptedException e) {
                   // TODO Auto-generated catch block
                   e.printStackTrace();
                 }
               }
             } else {
               continue;
             }
           }
         }
       } catch (IOException e) {
         System.out.println("error is " + e);
       } finally {
    
         if (bos != null) {
           try {
             // 把成功的送书记录到文件
             bos.write((count + "
    ").getBytes());
             bos.flush();
             System.out.println("bos will colse");
             bos.close();
           } catch (IOException e) {
             // TODO Auto-generated catch block
             System.out.println("error is " + e);
           }
         }
       }
    

    登录后就是解析收集到的文章url,然后打开url,拼接评论请求url,以及请求参数,发起post请求,评论上三次以后就会被网站服务器限制,提示评论太快,需要睡眠2秒钟再继续,最后会把评论成功的url和数量记录到本地文件中,便于查看。




    本公众号免费提供csdn下载服务,海量IT学习资源,如果你准备入IT坑,励志成为优秀的程序猿,那么这些资源很适合你,包括但不限于java、go、python、springcloud、elk、嵌入式 、大数据、面试资料、前端 等资源。同时我们组建了一个技术交流群,里面有很多大佬,会不定时分享技术文章,如果你想来一起学习提高,可以公众号后台回复【2】,免费邀请加技术交流群互相学习提高,会不定期分享编程IT相关资源。


    扫码关注,精彩内容第一时间推给你

    image

  • 相关阅读:
    【Git】时光机命令—Git命令
    【Vue.js】vue引入组件报错:该组件未注册?
    【CSS】flex布局初认识
    【Vue.js】基于vue的实时搜索,在结果中高亮显示关键词
    MyBatis介绍并解决jdbc编程的问题
    MyBatis中 #{} 和 ${}的区别
    Mybatis执行操作时控制台日志中显示sql语句
    Mybatis中常见操作(基本操作+动态sql+sql片段+关联映射(resultMap))
    Spring配置初始化和销毁的方法
    平时工作常用linux命令总结
  • 原文地址:https://www.cnblogs.com/liabio/p/11714267.html
Copyright © 2011-2022 走看看