webmagic學習資料:http://webmagic.io/docs/
原本爬蟲的計划是去扒b站的,結果發現b站是js動態加載的,所以先對豆瓣進行嘗試,練一下手.
整個項目核心是DoubanProcessor的這個類,繼承了webmagic的PageProcessor
其他是自己實現數據庫持久化的.
下面附上DoubanProcessor代碼,具體思路在注釋里,代碼后附上練習中遇到的幾個常見問題.
爬的頁面是:https://www.douban.com/doulist/3907668/
先來看豆列單項:

再來看豆列的html代碼pattern:
1 <div class="post"> 2 <a href="https://movie.douban.com/subject/6080802/" target="_blank"> 3 <img width="100" src="https://img1.doubanio.com/view/subject/l/public/s4695449.jpg"/> 4 </a> 5 </div> 6 <div class="title"> 7 <a href="https://movie.douban.com/subject/6080802/" target="_blank"> 8 今生只愛你 君だけに愛を Love Forever 9 </a> 10 </div> 11 12 <div class="rating"> 13 <span class="allstar00"></span> 14 <span>暫無評分</span> 15 </div> 16 <div class="abstract"> 17 18 導演: 細野英延 / 五木田亮一 19 <br /> 20 主演: 野村宏伸 / 松下由樹 21 <br /> 22 類型: 愛情 23 <br /> 24 制片國家/地區: 日本 25 <br /> 26 年份: 1991 27 </div>
以下我的DoubanProcessor實現:
1 public class DoubanProcessor implements PageProcessor{ 2 private Site site = Site.me().setUserAgent("Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0").setRetryTimes(3).setSleepTime(1000); 3 4 @Override 5 public void process(Page page) { 6 List<String> titles = page.getHtml().xpath("//div[@class='title']/a/text()").all(); //這是匹配標題 7 List<String> movieUrls = page.getHtml().xpath("//div[@class='post']/a").links().all(); //這是匹配電影url 8 List<String> ratings = page.getHtml().xpath("//div[@class='rating']/span[@class='rating_nums']/text()").all(); //這是匹配評分 9 List<String> attrFields = page.getHtml().xpath("//div[@class='abstract']").all(); //這是匹配下方的abstract標簽里的屬性項 10 for (int i = 0; i < titles.size(); i++) { //循環存儲到數據庫 11 DoubanList doubanList=new DoubanList(); 12 doubanList.setTitle(titles.get(i)); 13 doubanList.setMovieUrl(movieUrls.get(i)); 14 doubanList.setRating(ratings.get(i)); 15 String[] movieAttrs = attrFields.get(i).split("<br>"); 16 if(movieAttrs.length>4) { 17 doubanList.setDirector(movieAttrs[0].substring(23).trim()); 18 doubanList.setActor(movieAttrs[1].trim()); 19 doubanList.setType(movieAttrs[2].trim()); 20 doubanList.setTime(movieAttrs[4].substring(0, 9).trim()); 21 }else { 22 doubanList.setDirector(attrFields.get(i)); 23 } 24 DoubanListDao.save(doubanList); 25 } 26 } 27 28 @Override 29 public Site getSite() { 30 return site; 31 } 32 33 public static void main(String[] args) { 34 Spider.create(new DoubanProcessor()) 35 .addUrl("https://www.douban.com/doulist/3907668/") //設置爬的url 36 .addPipeline(new ConsolePipeline()) //會output到控制台...在這里並不需要,因為持久化到數據庫了 37 .thread(5) 38 .run(); 39 } 40 }
下面講講過程中遇到的問題:
1)403問題:我看了很多博文,發現其實全是互相抄襲.如果嘗試的網站不同,你會發現你很容易遇到403問題.也就是返回status code為403,網站拒絕訪問.其實原因是我們的工具請求沒有攜帶相應的header,所以我在site里調用setUserAgent去設置了UA,至於UA的參數,是從自己的瀏覽器直接抓包復制過來的.於是問題解決了.
實際上,訪問過快也可能造成403,在一些情況下還需要帶cookie/多個IP爬等等.
2)匹配多個的問題:看很多文章的時候,基本都是直接page.getHtml().xpath()然后調用get() 或者toString(),實際上看代碼發現,這里只能拿一個數據,而我需要匹配多個,因此要使用all();
Selectable接口注釋:
1 /** 2 * multi string result 3 * 4 * @return multi string result 5 */ 6 public List<String> all();
解決了這些問題,其實還有一個問題.
豆瓣的電影格式,會存在沒有導演,主演等信息的情況!!!....所以很坑....所以我添加了數組長度判斷,防止越界,而且實在電影屬性少的時候,就直接存到DB的director字段里.下面是數據庫儲存概括:

下次開始嘗試爬B站!
