Phinehasz Zhi

超越你看到的

爬虫入门(二)用webmagic爬豆瓣豆列的尝试(解决403等常见问题)

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站!

 

posted @ 2018-05-20 20:01  phinehasz  阅读(2450)  评论(1编辑  收藏  举报