zoukankan      html  css  js  c++  java
  • webmagic爬取博客园所有文章

    最近学习了下webmagic,学webmagic是因为想折腾下爬虫,但是自己学java的,又不想太费功夫,所以webmagic是比较好的选择了。

    写了几个demo,源码流程大致看了一遍。想着把博客园的文章列表爬下来吧。

    首页显示的就是第一页文章的列表,

    但是翻页按钮不是链接,而是动态的地址:

    实际请求的地址及参数:

    针对这个动态页面的情况,有两种解决方案:

    1. webmagic模拟post请求,获取返回页面。

     1 public class CnblogsSpider implements PageProcessor {
     2 
     3     private Site site = Site.me().setRetryTimes(3).setSleepTime(1000).setTimeOut(10000)
     4             .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
     5 
     6     public static final String URL_LIST = "https://www.cnblogs.com/mvc/AggSite/PostList.aspx";
     7 
     8     public static int pageNum = 1;
     9 
    10     public void process(Page page) {
    11 
    12         if (page.getUrl().regex("^https://www\.cnblogs\.com$").match()) {
    13             try {
    14                 page.addTargetRequests(page.getHtml().xpath("//*[@id="post_list"]/div/div[@class='post_item_body']/h3/a/@href").all());
    15                 pageNum++;
    16              //模拟post请求
    17                 Request req = new Request();
    18                 req.setMethod(HttpConstant.Method.POST);
    19                 req.setUrl("https://www.cnblogs.com/mvc/AggSite/PostList.aspx");
    20                 req.setRequestBody(HttpRequestBody.json("{CategoryType: 'SiteHome', ParentCategoryId: 0, CategoryId: 808, PageIndex: " + pageNum
    21                         + ", TotalPostCount: 4000,ItemListActionName:'PostList'}", "utf-8"));
    22                 page.addTargetRequest(req);
    23             } catch (Exception e) {
    24                 e.printStackTrace();
    25             }
    26         } else if (page.getUrl().regex(URL_LIST).match() && pageNum <= 200) {
    27             try {           
    28                 Thread.sleep(5000);
    29                 List<String> urls = page.getHtml().xpath("//*[@class='post_item']//div[@class='post_item_body']/h3/a/@href").all();
    30                 page.addTargetRequests(urls);
    31                 //模拟post请求
    32                 Request req = new Request();
    33                 req.setMethod(HttpConstant.Method.POST);
    34                 req.setUrl("https://www.cnblogs.com/mvc/AggSite/PostList.aspx");
    35                 req.setRequestBody(HttpRequestBody.json("{CategoryType: 'SiteHome', ParentCategoryId: 0, CategoryId: 808, PageIndex: " + ++pageNum
    36                         + ", TotalPostCount: 4000,ItemListActionName:'PostList'}", "utf-8"));
    37                 page.addTargetRequest(req);
    38                 System.out.println("CurrPage:" + pageNum + "#######################################");
    39 
    40             } catch (Exception e) {
    41                 e.printStackTrace();
    42             }
    43         } else {
    44             // 获取页面需要的内容,这里只取了标题,其他信息同理。
    45             System.out.println("抓取的内容:" + page.getHtml().xpath("//a[@id='cb_post_title_url']/text()").get());
    46         }
    47     }
    48 
    49     public Site getSite() {
    50         return site;
    51     }
    52 
    53     public static void main(String[] args) {
    54         Spider.create(new CnblogsSpider()).addUrl("https://www.cnblogs.com").thread(3).run();
    55     }
    56 }

    2.使用webmagic-selenium 

     1 public class SeleniumCnblogsSpider implements PageProcessor {
     2 
     3     private Site site = Site.me().setRetryTimes(3).setSleepTime(1000).setTimeOut(10000)
     4             .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
     5 
     6     public static final String URL_LIST = "https://www\.cnblogs\.com/#p\d{1,3}";
     7 
     8     public static int pageNum = 1;
     9 
    10     public void process(Page page) {
    11 
    12         
    13         if (page.getUrl().regex("^https://www\.cnblogs\.com$").match()) {//爬取第一页
    14             try {
    15                 page.addTargetRequests(page.getHtml().xpath("//*[@id="post_list"]/div/div[@class='post_item_body']/h3/a/@href").all());
    16 
    17                 pageNum++;
    18                 page.addTargetRequest("https://www.cnblogs.com/#p2");
    19             } catch (Exception e) {
    20                 e.printStackTrace();
    21             }
    22         } else if (page.getUrl().regex(URL_LIST).match() && pageNum <= 200) {//爬取2-200页,一共有200页
    23             try {
    24                 List<String> urls = page.getHtml().xpath("//*[@class='post_item']//div[@class='post_item_body']/h3/a/@href").all();
    25                 page.addTargetRequests(urls);
    26 
    27                 page.addTargetRequest("https://www.cnblogs.com/#p" + ++pageNum);
    28                 System.out.println("CurrPage:" + pageNum + "#######################################");
    29 
    30             } catch (Exception e) {
    31                 e.printStackTrace();
    32             }
    33         } else {
    34             // 获取页面需要的内容
    35             System.out.println("抓取的内容:" + page.getHtml().xpath("//a[@id='cb_post_title_url']/text()").get());
    36         }
    37     }
    38 
    39     public Site getSite() {
    40         return site;
    41     }
    42 
    43     public static void main(String[] args) {
    44         System.setProperty("selenuim_config", "D:/config.ini");//配置文件,我用的webmagic0.7.2,低版本可能不需要该文件,但也不支持phantomjs.
    45         Downloader downloader = new SeleniumDownloader();//调用seleniumdownloader,这个downlaoder可以驱动selenium,phantomjs等方式下载,由config.ini配置
    46         downloader.setThread(10);
    47         Spider.create(new SeleniumCnblogsSpider()).setDownloader(downloader).addUrl("https://www.cnblogs.com").thread(10).runAsync();
    48     }
    49 }

    另附我的config.ini和pom文件:

     1 # What WebDriver to use for the tests
     2 driver=phantomjs
     3 #driver=firefox
     4 #driver=chrome
     5 #driver=http://localhost:8910
     6 #driver=http://localhost:4444/wd/hub
     7 
     8 # PhantomJS specific config (change according to your installation)
     9 #phantomjs_exec_path=/Users/Bingo/bin/phantomjs-qt5
    10 phantomjs_exec_path=d:/phantomjs.exe
    11 #phantomjs_driver_path=/Users/Bingo/Documents/workspace/webmagic/webmagic-selenium/src/main.js
    12 phantomjs_driver_loglevel=DEBUG
     1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     2     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     3     <modelVersion>4.0.0</modelVersion>
     4     <groupId>com.summit</groupId>
     5     <artifactId>WebMagicDemo</artifactId>
     6     <version>0.0.1-SNAPSHOT</version>
     7 
     8     <dependencies>
     9         <dependency>
    10             <groupId>us.codecraft</groupId>
    11             <artifactId>webmagic-core</artifactId>
    12             <version>0.7.2</version>
    13         </dependency>
    14         <dependency>
    15             <groupId>us.codecraft</groupId>
    16             <artifactId>webmagic-extension</artifactId>
    17             <version>0.7.2</version>
    18         </dependency>
    19         <dependency>
    20             <groupId>us.codecraft</groupId>
    21             <artifactId>webmagic-selenium</artifactId>
    22             <version>0.7.2</version>
    23         </dependency>
    24         <dependency>
    25             <groupId>org.seleniumhq.selenium</groupId>
    26             <artifactId>selenium-java</artifactId>
    27             <version>2.41.0</version>
    28         </dependency>
    29     </dependencies>
    30 </project>

    如果依赖版本与此不一致,可能会出问题。

    后记:

      本文主要记录了我在解决webmagic爬取动态页面的心得。

      方法1在可以获取动态访问地址的情况下用,比如通过调试工具,我可以找到第二页实际的访问地址是:https://www.cnblogs.com/mvc/AggSite/PostList.aspx,用这种方法实测效率比较高。但复杂场景下不推荐。

      方法2主要是针对复杂场景,在实际地址很难找或者隐藏,网站有反扒措施的情况下通常很好用,因为它是模拟的实际的浏览器,比较耗费资源,效率比方法1低 。  

      webmagic0.7.2 支持selenium (chrome),phantomjs的模拟浏览器行为的方式获取页面。我在方法2中使用的是phantomjs下载的。selenium 的方式我也试过,但是每次调用下载就会弹出浏览器窗口,很是不爽,也没找到如何解决,所以就不推荐了。

    抓取结果截图:

     

  • 相关阅读:
    POJ1239
    HDU 2829 四边形不等式优化
    返回数字二进制的最高位位数o(n)
    矩阵快速幂 模板
    HDU4718 The LCIS on the Tree(LCT)
    HDU4010 Query on The Trees(LCT)
    HDU3487 Play With Chains(Splay)
    CF444C DZY Loves Colors
    HDU4836 The Query on the Tree(树状数组&&LCA)
    HDU4831&&4832&&4834
  • 原文地址:https://www.cnblogs.com/tibit/p/7136762.html
Copyright © 2011-2022 走看看