【Java爬虫】学爬虫从简单的开始,无门槛小白都能学会,带你爬取豆瓣电影Top250

news/2024/7/19 12:23:32 标签: java, 爬虫, 编程语言

闲扯几句

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

看到网上很多的爬虫代码都是基于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> 标签,在这个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.jsoup</groupId>
   <artifactId>jsoup</artifactId>
   <version>1.13.1</version>
</dependency>

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

接下来就开始撸了呗。因为我们请求的所有数据分为10页,所以我们写个循环,从0开始:

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

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

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

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

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

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

拿到文档对象后,我们就获取每个电影的div,分析网页可以看到,它的class是item

所以我们通过getElementsByClass方法批量从网页中获取class=item的元素:

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

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

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

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

  1. 电影排名

    很简单啊,直接获取item中第一个em标签的文本就可以了:
java">String num = item.getElementsByTag("em").get(0).text();
  1. 电影名称

    获取item 下的第一个class=hd div的第一个span的文本
java">String title = item.getElementsByClass("hd").get(0).getElementsByTag("span").get(0).text();
  1. 演员信息、电影年份、国家、电影类型

    注意这里,演员信息在一个p标签里,但是p标签的文本分成了两部分,用 <br>隔开,所以我们先要获取到 p 标签的html文本,然后根据 <br> 多html文本进行分割,分别获取演员信息电影年份国家电影类型等数据:
java">String bd = item.getElementsByClass("bd").get(0).getElementsByTag("p").get(0).html();
String actor = bd.split("<br>")[0].replaceAll("&nbsp;", " "); // 演员信息,注意替换空格符号
String info = bd.split("<br>")[1].replaceAll("&nbsp;", " ");
String[] infos = info.split("/");   // 下面的三个数据通过 '/' 来分割
String year = infos[0].trim();   // 电影年份
String country = infos[1].trim();   // 国家
String type = infos[2].trim();   // 电影类型
  1. 电影评分

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

java">String ratingNum = item.getElementsByClass("rating_num").get(0).text(); // 获取评分
  1. 电影简评

    这个跟评分类似,获取第一个 calss=quote 标签的文本就可以了:
java">String quote = item.getElementsByClass("quote").get(0).text();

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

java">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("<br>")[0].replaceAll("&nbsp;", " ");
                String info = bd.split("<br>")[1].replaceAll("&nbsp;", " ");
                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,也就是这段代码:

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

获取简评失败了。

再看是第几个电影的数据出问题:

第200个电影是好的,那就是说它的下一个 201 出问题了。我们翻到这一页看下网页是啥样的:

果然,这个名叫 哈利·波特与火焰杯 的电影没有简介,那就是说没这个标签啊,怪不得获取失败了。

那咋办呢?我们这里就需要对异常信息进行一个处理,不能让程序中断。

java">String quote = "";
if (item.getElementsByClass("quote").size() > 0) {
    quote = item.getElementsByClass("quote").get(0).text();
}

再跑一次:

程序完整运行下来了,而且电影信息全部拿到了,也就是说我们这次关于豆瓣电影 top250的数据爬取成功了。

结尾

好了,以上就是我这期给您带来的一个Java爬虫入门小案例。从需求分析思路整理再到代码细节错误处理都有非常详细的解析说明,并且代码执行的每一步都配置了图片说明哦。你说,我是不是个贴心的大暖男🥰

后期我会更新更多关于Java爬虫的小案例带你一起学习、提升,发现更多有趣的事情,别忘记关注我哟😋

希望这个冬天里,有我你不再寒冷;
希望漆黑夜晚里,有我你不再孤独。


我是程序员青戈,一个有情怀、有理想的一线码农,先后在IBM、阿里、科大讯飞采坑~

欢迎您关注我的个人原创公众号:Java学习指南,这里只分享知识干货,不贩卖焦虑,有温度、有深度。

感谢您的阅读,我们下期再见~


http://www.niftyadmin.cn/n/887816.html

相关文章

爬了1000张清纯妹子私房照,我流鼻血了...

闲扯几句 大家好&#xff0c;我是你们的老朋友青戈&#xff0c;之前分享了一篇Java爬虫的入门实战教程&#xff0c;收获了不少赞&#xff0c;看来大家伙对爬虫的热情度还是蛮高的哈。既然大家都这么想学爬虫&#xff0c;那今天就安排点刺激的。那你要非问我有多刺激&#xff0…

Java面试合集(一)Java基础知识点汇总

大家好&#xff0c;我是 程序员青戈&#xff0c;一个被Bug耽误了才艺的程序员&#x1f466;专注于Java领域的知识分享和技术交流&#xff0c;每天都会给大家带来Java学习的干货教程&#x1f4da; 微信搜索公众号 Java学习指南&#xff0c;回复 面试 领取一线大厂面试题一套&…

分享一个开源的Springboot博客系统,界面简洁精致,拿来即用

文章目录系统简介主要技术与框架环境设置页面展示项目待优化获取方式系统简介 本期给大家带来一款基于Springboot的博客系统。 博客系统通过从零开始搭建整个项目&#xff0c;会带你了解整个开发流程&#xff0c;如何设计&#xff0c;如何实现&#xff0c;一步步发现&#xf…

面试官问你:知道什么是ABA问题吗?

大家好啊&#xff0c;我是你们的老朋友青戈&#xff0c;我又来分享干货啦&#x1f609;最近有没有好好学习啊&#xff1f;我不在的时候也不能懈怠哦~毕竟升职加薪还得靠自己努力的呀&#x1f606; 在开始问题阐述之前呢&#xff0c;我们先看一则小故事&#xff1a; 狸猫换太子…

面试中被问到CAS机制该怎么回答

一个小例子说说什么是线程安全 并发是Java编程的基础&#xff0c;在我们日常的工作中&#xff0c;很多时候都会跟并发打交道&#xff0c;当然&#xff0c;这也是面试考察的重点。在并发编程中&#xff0c;被提起最多的概念是线程安全&#xff0c;下面我们先来看一段代码&#…

ecshop 商品详情页面显示-赠品信息-优惠活动

在goods.php中搜索$goods get_goods_info($goods_id);然后下下一行中&#xff0c;添加下面的代码 /* 取得用户等级 */ $user_rank_list array();$user_rank_list[0] $_LANG[not_user];$sql "SELECT rank_id, rank_name FROM " . $ecs->table(user_rank);…

关于Mysql分库分表,面试的时候怎么回答比较好呢?

前言 公司最近在搞服务分离&#xff0c;数据切分方面的东西&#xff0c;因为单张包裹表的数据量实在是太大&#xff0c;并且还在以每天60W的量增长。 之前了解过数据库的分库分表&#xff0c;读过几篇博文&#xff0c;但就只知道个模糊概念&#xff0c; 而且现在回想起来什么…

经验:一个普通的二本学生如何拿到大厂的offer?

大家好&#xff0c;我是程序员青戈&#xff0c;本期分享一位二本普通学生逆袭斩获大厂offer的故事&#xff0c;请大家细细品读&#xff0c;相信从中会有所收获和感触的。 1、终于步入大学 我既没有跨过山和大海&#xff0c;也没有穿过人山人海&#xff0c;我就是我&#xff0c…