专栏名称: 武哥聊编程
这里有技术,有段子,有生活,也有资源,要不然怎么叫 “私房菜” 呢?
目录
相关文章推荐
新北方  ·  最新:这类微短剧不得上线传播! ·  昨天  
新北方  ·  95.10亿元!创造新纪录! ·  2 天前  
普象工业设计小站  ·  家电界「爱马仕」,贵不动了? ·  3 天前  
51好读  ›  专栏  ›  武哥聊编程

谁说Java不能搞爬虫,武哥带你一起爬取豆瓣电影Top250

武哥聊编程  · 公众号  ·  · 2020-12-16 10:30

正文

闲扯几句

大家好,本期我准备了一篇爬虫的教程,也是从最基础的网页爬虫开始,给大家讲讲网页爬虫的小技巧。

看到网上很多的爬虫代码都是基于 python 的,那作为一名 Java工程师 的我就有点不服气了,Java难道不能做爬虫吗?我想写个爬虫是不是还得先学会 python ?程序员的头发不知道多宝贵吗?花那么多时间学习语言,是想造孽啊?救救孩子吧,救救我我本来就日渐稀疏的头发吧。 我命由我不由天,我今天就自己来试试看,看看Java写个爬虫是有多费劲?看懂的朋友别忘记给我个 三连 哈,毕竟我是堵上了咱们Java程序员的 荣誉 在奋战!奥利给!

网页分析

话不多说,开整!

先打开我要爬取数据的网页:豆瓣电影Top250 我们先来分析一下这个网页,看看哪些数据比较有价值。

「No.1」 的经典越狱电影《肖申克的救赎》举例子,我们可以看到的数据有:

  1. 排名
  2. 电影名称
  3. 导演和演员信息
  4. 电影上映年份
  5. 电影所属的国家
  6. 电影类型
  7. 电影评分
  8. 电影评价数
  9. 电影简评

OK,分析完一个网页结构,确定好了我们需要的数据,那么我们准备开始写程序批量抓取了。

思路讲解

写代码之前,我们先不要着急,先理一理思路。你知道,写代码最重要的就是思路,思路理顺了,可以说你的代码已经完成了一半。那剩下的一半干嘛?写bug,调bug呗🤣

打开网页豆瓣电影Top250按下 「f12」 ,看到下面这个界面 我们一起来分析一下数据,讲一讲怎么抓取。

点击左上角这个箭头,然后选中网页对应的位置,在下面就会出现这个位置对应的html代码。

先整体看一下,可以看到每个电影都是一个

  • 标签,在这个li标签里面存放着这个电影相关的全部html代码: 再打开li标签,可以看到,每个li标签里面都是一个 class='item' div ,这个div就是我们需要获取数据的最外层div了。然后我们从这个div往下看,找到对应数据存放的标签即可。

    比如这个电影排名: 我们可以从下面的 em 标签里面找到,那我们只需要一层层往下解析这个html代码,找到这个 em 标签,获取出里面的文本就行了。其他的数据也是异曲同工,我们可以按照这个套路都找一下对应的标签的位置,然后抓取。 怎么样,很简单是吧?那么下面就开始写bug吧

    撸代码

    写代码之前先喝杯咖啡,润润肺,找找灵感,你知道5k程序员和50k程序员的差别在哪里吗?

    仪式感! 我跟你说,仪式感非常重要,包括生活中也是,你不能把自己过成穷屌丝的样子,要不然这辈子抬不起头来,你要假装自己是亿万富翁,然后花钱去享受,再然后回到一穷二白。如果你非要问我为什么要有这段经历,那不就是死要面子活受罪么...

    咳咳,扯远了,继续回到正题哈。

    我这次使用的插件是 Jsoup ,相信很多小伙伴都听说过它的大名啊,没错,它是一个非常适合做网页html解析的第三方类库,而且它可以直接连接目标网址,获取数据,无需使用其他的http请求工具,非常的方便,适合小白。

    第一步:创建maven工程

    为什么使用maven工程?

    那还用问啊,当然是方便啊,我总不能去网上下载jar包导进idea吧,那太low了,不符合我的气质啊,所以你自己拿捏了哈,同学。

    创建maven工程具体的步骤我就不在这里赘述了,网上教程一搜一大堆。我们创建好工程后直接在pom里导入依赖:

    <dependency>
       <groupId>org.jsoupgroupId>
       <artifactId>jsoupartifactId>
       <version>1.13.1version>
    dependency>

    对,是她了,我们的主角 jsoup

    接下来就开始撸了呗。因为我们请求的所有数据分为10页,所以我们写个循环,从0开始: 第一页的url是这样的: https://movie.douban.com/top250?start=0&filter=

    第二页的url是这样的: https://movie.douban.com/top250?start=25&filter=

    可以看出来,通过 start 这个参数可以控制切换分页,那么我们就在循环里制造这样的参数:

    for (int i = 0; i 10; i++) {
     int page = i * 25;  // 制造分页参数
    }

    下面就开始通过 Jsoup 发送http请求获取网页html代码,这里的document就是整个文档对象,我们可以从中获取各种标签的数据。

    
    
    
    
    
        
     Document document = Jsoup.connect("https://movie.douban.com/top250?start="+ page).get();

    拿到文档对象后,我们就获取每个电影的div,分析网页可以看到,它的class是 item 所以我们通过 getElementsByClass 方法批量从网页中获取 class=item 的元素:

    Elements items = document.getElementsByClass("item");  // 批量获取当前页中class=item的元素

    然后开始遍历所有的 item ,依次获取他们的电影相关的数据:

    for (Element item : items) {
     // 每个item中都包含当前电影的所有数据
    }

    再来分析网页,依次拿到我们需要的数据

    1. 「电影排名」 很简单啊,直接获取 item 中第一个 em 标签的文本就可以了:
    String num = item.getElementsByTag("em").get(0).text();
    1. 「电影名称」 获取 item 下的第一个 class=hd div的第一个span的文本
    String title = item.getElementsByClass("hd").get(0).getElementsByTag("span").get(0).text();
    1. 「演员信息、电影年份、国家、电影类型」 注意这里,演员信息在一个 p 标签里,但是 p 标签的文本分成了两部分,用
      隔开,所以我们先要获取到 p 标签的html文本,然后根据
      多html文本进行分割,分别获取 演员信息 电影年份 国家 电影类型 等数据:
    String bd = item.getElementsByClass("bd").get(0).getElementsByTag("p").get(0).html();
    String actor = bd.split("
    "
    )[0].replaceAll(" "" "); // 演员信息,注意替换空格符号
    String info = bd.split("
    "
    )[1].replaceAll(" "" ");
    String[] infos = info.split("/");   // 下面的三个数据通过 '/' 来分割
    String year = infos[0].trim();   // 电影年份
    String country = infos[1].trim();   // 国家
    String type = infos[2].trim();   // 电影类型
    1. 「电影评分」

      这个就比较简单了,直接获取第一个 class=rating_num 标签的文本就可以了:

    String ratingNum = item.getElementsByClass("rating_num").get(0).text(); // 获取评分
    1. 「电影简评」 这个跟评分类似,获取第一个 calss=quote 标签的文本就可以了:
    String quote = item.getElementsByClass("quote").get(0).text();

    Ok,到这里所有的代码就写完了,怎么样,是不是跟着思路走分析起来很容易呢?你自己可以试试哦,这里是完整的代码:

    for (int i = 0; i 10; i++) {
                int page = i * 25;
                Document document = Jsoup.connect("https://movie.douban.com/top250?start="+ page).get();
                Elements items = document.getElementsByClass("item");
                for (Element item : items) {
                    String num = item.getElementsByTag("em").get(0).text();
                    String title = item.getElementsByClass("hd").get(0).getElementsByTag("span").get(0).text();
                    String bd = item.getElementsByClass("bd").get(0).getElementsByTag("p").get(0).html();
                    String actor = bd.split("
    "
    )[0].replaceAll(" "" ");
                    String info = bd.split("
    "
    )[1].replaceAll(" "" ");
                    String[] infos = info.split("/");
                    String year = infos[0].trim();
                    String country = infos[1].trim();
                    String type = infos[2].trim();
                    String ratingNum = item.getElementsByClass("rating_num").get(0).text();
                    String quote = item.getElementsByClass("quote").get(0).text();

                    System.out.println("电影名次: " + num);
                    System.out.println("电影标题: " + title);
                    System.out.println("电影演员: " + actor);
                    System.out.println("电影年份: " + year);
                    System.out.println("国家: " + country);
                    System.out.println("电影类型: " + type);
                    System.out.println("电影评分: " + ratingNum);
                    System.out.println("电影简评: " + quote);
                    System.out.println("============================================");
                }
            }

    写完之后,我们运行一下代码,看看代码有没有问题。 果然,出问题了,哈哈哈,很快哈,啪的一下就出来了。

    这是个啥错误?

    一看,数组越界了,我心中已经猜想到答案了,肯定是获取的数据缺少了点什么导致的。我们定位到问题行: 25 ,也就是这段代码:

    String quote = item.getElementsByClass("quote").get(0).text();

    获取简评失败了。

    再看是第几个电影的数据出问题: 第200个电影是好的,那就是说它的下一个 201 出问题了。我们翻到这一页看下网页是啥样的: 果然,这个名叫 哈利·波特与火焰杯 的电影没有简介,那就是说没这个标签啊,怪不得获取失败了。







  • 请到「今天看啥」查看全文


    推荐文章
    新北方  ·  95.10亿元!创造新纪录!
    2 天前
    普象工业设计小站  ·  家电界「爱马仕」,贵不动了?
    3 天前
    老子道德经  ·  上床之前你应该先看看这个
    8 年前
    政事儿  ·  前总理之子的“大白话”
    7 年前
    剑圣喵大师  ·  为什么我们需要与陌生人交流
    7 年前
    青松医药集团  ·  2017年5月25日三分钟医药新闻早餐
    7 年前