这是 Java 网络爬虫系列文章的第一篇,若是你还不知道 Java 网络爬虫系列文章,请参看 学 Java 网络爬虫,须要哪些基础知识。第一篇是关于 Java 网络爬虫入门内容,在该篇中咱们以采集虎扑列表新闻的新闻标题和详情页为例,须要提取的内容以下图所示:css
咱们须要提取图中圈出来的文字及其对应的连接,在提取的过程当中,咱们会使用两种方式来提取,一种是 Jsoup 的方式,另外一种是 httpclient + 正则表达式的方式,这也是 Java 网络爬虫经常使用的两种方式,你不了解这两种方式不要紧,后面会有相应的使用手册。在正式编写提取程序以前,我先交代一下 Java 爬虫系列博文的环境,该系列博文全部的 demo 都是使用 SpringBoot 搭建的,无论你使用哪一种环境,只须要正确的导入相应的包便可。html
咱们先来使用 Jsoup 的方式提取新闻信息,若是你还不知道 Jsoup ,请参考 jsoup.org/java
先创建一个 Springboot 项目,名字就随意啦,在 pom.xml 中引入 Jsoup 的依赖git
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.12.1</version>
</dependency>
复制代码
好了,接下来咱们一块儿分析页面吧,想必你还没浏览过吧,点击这里浏览虎扑新闻。在列表页中,咱们利用 F12 审查元素查看页面结构,通过咱们分析发现列表新闻在 <div class="news-list">
标签下,每一条新闻都是一个li
标签,分析结果以下图所示:github
因为咱们前面已经知道了 css 选择器,咱们结合浏览器的 Copy 功能,编写出咱们 a
标签的 css 选择器代码:div.news-list > ul > li > div.list-hd > h4 > a
,一切都准备好了,咱们一块儿来编写 Jsoup 方式提取信息的代码:正则表达式
/** * jsoup方式 获取虎扑新闻列表页 * @param url 虎扑新闻列表页url */
public void jsoupList(String url){
try {
Document document = Jsoup.connect(url).get();
// 使用 css选择器 提取列表新闻 a 标签
// <a href="https://voice.hupu.com/nba/2484553.html" target="_blank">霍华德:夏休期内曾节食30天,这考验了个人身心</a>
Elements elements = document.select("div.news-list > ul > li > div.list-hd > h4 > a");
for (Element element:elements){
// System.out.println(element);
// 获取详情页连接
String d_url = element.attr("href");
// 获取标题
String title = element.ownText();
System.out.println("详情页连接:"+d_url+" ,详情页标题:"+title);
}
} catch (IOException e) {
e.printStackTrace();
}
}
复制代码
使用 Jsoup 方式提取仍是很是简单的,就五、6行代码就完成了,关于更多 Jsoup 如何提取节点信息的方法能够参考 jsoup 的官网教程。咱们编写 main 方法,来执行 jsoupList 方法,看看 jsoupList 方法是否正确。数据库
public static void main(String[] args) {
String url = "https://voice.hupu.com/nba";
CrawlerBase crawlerBase = new CrawlerBase();
crawlerBase.jsoupList(url);
}
复制代码
执行 main 方法,获得以下结果:apache
上面咱们使用了 Jsoup 方式正确提取了虎扑列表新闻,接下来咱们使用 httpclient + 正则表达式的方式来提取,看看使用这种方式又会涉及到哪些问题?httpclient + 正则表达式的方式涉及的知识点仍是蛮多的,它涉及到了正则表达式、Java 正则表达式、httpclient。若是你还不知道这些知识,能够点击下方连接简单了解一下:浏览器
正则表达式:正则表达式微信
Java 正则表达式:Java 正则表达式
httpclient:httpclient
咱们在 pom.xml 文件中,引入 httpclient 相关 Jar 包
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.10</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.10</version>
</dependency>
复制代码
关于虎扑列表新闻页面,咱们在使用 Jsoup 方式的时候进行了简单的分析,这里咱们就不在重复分析了。对于使用正则表达式方式提取,咱们须要找到可以表明列表新闻的结构体,好比:<div class="list-hd"> <h4> <a href="https://voice.hupu.com/nba/2485508.html" target="_blank">直上云霄!魔术官方社媒晒富尔茨扣篮炫酷特效图</a></h4></div>
这段结构体,每一个列表新闻只有连接和标题不同,其余的都同样,并且 <div class="list-hd">
是列表新闻特有的。最好不要直接正则匹配 a
标签,由于 a
标签在其余地方也有,这样咱们就还须要作其余的处理,增长咱们的难度。如今咱们了解了正则结构体的选择,咱们一块儿来看看 httpclient + 正则表达式方式提取的代码:
/** * httpclient + 正则表达式 获取虎扑新闻列表页 * @param url 虎扑新闻列表页url */
public void httpClientList(String url){
try {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpclient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
String body = EntityUtils.toString(entity,"utf-8");
if (body!=null) {
/* * 替换掉换行符、制表符、回车符,去掉这些符号,正则表示写起来更简单一些 * 只有空格符号和其余正常字体 */
Pattern p = Pattern.compile("\t|\r|\n");
Matcher m = p.matcher(body);
body = m.replaceAll("");
/* * 提取列表页的正则表达式 * 去除换行符以后的 li * <div class="list-hd"> <h4> <a href="https://voice.hupu.com/nba/2485167.html" target="_blank">与球迷亲切互动!凯尔特人官方晒球队开放训练日照片</a> </h4> </div> */
Pattern pattern = Pattern
.compile("<div class=\"list-hd\">\\s* <h4>\\s* <a href=\"(.*?)\"\\s* target=\"_blank\">(.*?)</a>\\s* </h4>\\s* </div>" );
Matcher matcher = pattern.matcher(body);
// 匹配出全部符合正则表达式的数据
while (matcher.find()){
// String info = matcher.group(0);
// System.out.println(info);
// 提取出连接和标题
System.out.println("详情页连接:"+matcher.group(1)+" ,详情页标题:"+matcher.group(2));
}
}else {
System.out.println("处理失败!!!获取正文内容为空");
}
} else {
System.out.println("处理失败!!!返回状态码:" + response.getStatusLine().getStatusCode());
}
}catch (Exception e){
e.printStackTrace();
}
}
复制代码
从代码的行数能够看出,比 Jsoup 方式要多很多,代码虽然多,可是总体来讲比较简单,在上面方法中我作了一段特殊处理,我先替换了 httpclient 获取的字符串 body 中的换行符、制表符、回车符,由于这样处理,在编写正则表达式的时候可以减小一些额外的干扰。接下来咱们修改 main 方法,运行 httpClientList 方法。
public static void main(String[] args) {
String url = "https://voice.hupu.com/nba";
CrawlerBase crawlerBase = new CrawlerBase();
// crawlerBase.jsoupList(url);
crawlerBase.httpClientList(url);
}
复制代码
运行结果以下图所示:
使用 httpclient + 正则表达式的方式一样正确的获取到了列表新闻的标题和详情页连接。到此 Java 爬虫系列博文第一篇就写完了,这一篇主要是 Java 网络爬虫的入门,咱们使用了 jsoup 和 httpclient + 正则的方式提取了虎扑列表新闻的新闻标题和详情页连接。固然这里还有不少没有完成,好比采集详情页信息存入数据库等。
但愿以上内容对你有所帮助,下一篇是模拟登录相关的,若是你对 Java 网络爬虫感兴趣,不妨关注一波,一块儿学习,一块儿进步。
源代码:点击这里
文章不足之处,望你们多多指点,共同窗习,共同进步
打个小广告,欢迎扫码关注微信公众号:「平头哥的技术博文」,一块儿进步吧。