这是voidAlex原创的第三篇博文。
源码在我的GitHub

爬虫

上一篇博文介绍了如何模拟登录和解析JSON数据,这篇博文介绍怎么爬取不需要登录的网站的信息。

上一篇博文中关于爬虫的介绍可以点这里查看。

引入JSOUP

pom.xml中添加JSOUP依赖:

1
2
3
4
5
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.2</version>
</dependency>

JSOUP是一款Java的HTML解析库,可以解析HTML中的文本内容。它的官网地址是https://jsoup.org/

查看网页源码

好了,要干正事了。Google一下妹子图,找到这两个网站:http://jandan.net/ooxxhttp://www.youmzi.com/tuinvlang.html.先看第一个,它的源码长这样:

我们要找的是所有的img标签里的URL,然后把它下载下来。但是这样似乎只能爬取单个页面的妹子图?所以我们还要找到下一页的URL:

恩,找到了。开始写代码吧!

downloadImage方法

首先写一个下载图片的方法,该方法传入图片的URL和要写入的路径,然后将文件写入本地。需要调用java.net包中的一些方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static boolean downloadImage(String imageUrl, String path) {
try {
//分割字符串,获得文件名
String filePath = path + imageUrl.substring(imageUrl.lastIndexOf("/"));
//获得文件流
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
InputStream in = connection.getInputStream();
//写入本地文件
File file = new File(filePath);
FileOutputStream out = new FileOutputStream(file);
int i = 0;
while ((i = in.read()) != -1){
out.write(i);
}
System.out.println(imageUrl + "下载成功");
out.close();
in.close();
return true;
}catch (Exception e){
System.out.println(imageUrl + "下载失败");
return false;
}
}

需要注意的是要设置超时的时间,要不然会导致很多的图片下载失败。

解析HTML

接下来我们需要理一理这个爬虫的思路:

  1. 打开这个网页。获取到网页所有图片的URL,然后遍历这些URL去下载图片;
  2. 当遍历结束后,去找下一页的URL,然后执行1;
  3. 直到找不到下一页的URL为止。

煎蛋妹子图

首先用jsoup中的方法获取到网页并且得到Document对象:

1
2
Document doc = null;
doc = Jsoup.connect(url).get();

获得所有的img标签:

1
Elements elements = doc.getElementsByTag("img");

遍历这些标签并且下载:

1
2
3
4
5
6
7
for (Element element : elements){
//获取标签中src属性的绝对路径
String imgSrc = element.attr("abs:src");
if (downloadImage(imgSrc, path)){
count ++;
}
}

获取下一页的地址,如果没有则退出循环:

1
2
3
4
5
6
7
try {
url = doc.getElementsByClass("previous-comment-page").get(0)
.getElementsByTag("a").attr("abs:href");
}catch (Exception e){
System.out.println("没链接了~");
break;
}

大功告成!

优妹子

第二个网站的略微复杂一点,上方有导航栏,每一页有若干个专题,点击进去了才是大图。所以需要爬取的链接稍微多一点。

首先还是获取到网页并且得到Document对象:

1
2
Document doc = null;
doc = Jsoup.connect(url).get();

然后获得每一个二级页面(即专题)的URL,并放到一个List里面:

1
2
3
4
5
Elements imageUrl = doc.getElementsByClass("tzpic3-mzindex").get(0).getElementsByTag("a");
ArrayList<String> urlList = new ArrayList<String>();
for (Element element : imageUrl){
urlList.add(element.attr("abs:href"));
}

对于List里的每一个URL,去找它每一个的img标签并且获取下一页的URL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
for (String s : urlList){
String next = s;
while (true){
try {
doc = Jsoup.connect(next).get();
}catch (IOException e){
System.out.println(url + "请求失败");
}
Element e = doc.getElementsByClass("arpic").get(0);
//获取所有img标签
Elements elements = e.getElementsByTag("img");
for (Element element : elements){
//获取标签中src属性的绝对路径
String imgSrc = element.attr("abs:src");
if (downloadImage(imgSrc, path)){
count ++;
}
}
String tmp = next;
try {
Elements nextPage = doc.getElementsByClass("jogger2").get(0).getElementsByTag("a");
next = null;
for (Element element : nextPage){
//获取标签中src属性的绝对路径
if (element.text().equals("下一页")){
next = element.attr("abs:href");
}
}
}catch (Exception ex){
System.out.println("没链接了~");
break;
}
if (next == null || tmp.equals(next)){
break;
}
}
}

运行

1
2
3
4
5
public static void main(String args[]) throws Exception{
String path = "image";
jiandan(path);
youmeizi(path);
}

跑了两个多小时终于跑完了,看一下战果:

恩,将近1w张。不说了,我先喝瓶营养快线去~