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 的方式我也試過,但是每次調用下載就會彈出瀏覽器窗口,很是不爽,也沒找到如何解決,所以就不推薦了。

抓取結果截圖:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM