使用Java爬蟲(chóng)爬取人民日?qǐng)?bào)公眾號(hào)頁(yè)面圖片
使用Java框架Jsoup和HttpClient實(shí)現(xiàn),先看代碼
爬取目標(biāo)頁(yè)面
1厚脉、使用Maven構(gòu)建一個(gè)普通Java工程
加入依賴(lài):
<!--用來(lái)解析Html頁(yè)面的第三方Jar-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.2</version>
</dependency>
<!--用來(lái)模擬Http客戶(hù)端的第三方Jar-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.1</version>
</dependency>
2浅缸、第一個(gè)類(lèi)浦楣,開(kāi)始爬取入口類(lèi)
package com.yomihu.spider;
import com.yomihu.parse.ParseHtml;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* mini-spider 單頁(yè)面爬取啟動(dòng)類(lèi)
*
* @Author 孫龍
* @Date 2018/1/28
*/
public class SinglePageSpiderStarter {
/**
* 開(kāi)始頁(yè)面的URL(一個(gè)微信公眾號(hào)的頁(yè)面)
*/
private static final String START_URL = "https://mp.weixin.qq.com/s/zzkEWbcb81pbsr-PJvVzQA";
/**
* 目標(biāo)圖片存放目錄
*/
private static final String IMG_SAVE_PATH = "E:/jj";
public static void main(String[] args) throws Exception {
//使用Jsoup將目標(biāo)Url的Html頁(yè)面獲取為Document變量
Document rootdocument = Jsoup.connect(START_URL).get();
List<String> urlList = new ArrayList<String>();
//將頁(yè)面中的目標(biāo)Url解析為列表
ParseHtml.singlePageParseImg(rootdocument, urlList);
//初始化HttpClient對(duì)象
CloseableHttpClient httpClient = HttpClients.createDefault();
//控制圖片名稱(chēng)的變量
int i = 0;
for (String url : urlList) {
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpClient.execute(httpGet);
InputStream inputStream = response.getEntity().getContent();
//保存圖片
File file = new File(IMG_SAVE_PATH);
if (!file.exists()) {
//不存在就創(chuàng)建該目錄
file.mkdirs();
}
String imgName = IMG_SAVE_PATH + File.separator + "test" + i + ".jpg";
//保存圖片
FileOutputStream fos = new FileOutputStream(imgName);
i++;
byte[] data = new byte[1024];
int len;
while ((len = inputStream.read(data)) != -1) {
fos.write(data, 0, len);
}
//釋放資源
response.close();
}
httpClient.close();
}
}
3蹭越、第二個(gè)類(lèi)抹恳,解析Html頁(yè)面
package com.yomihu.parse;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.List;
/**
* mini-spider Html頁(yè)面結(jié)構(gòu)解析
*
* @Author 孫龍
* @Date 2018/1/28
*/
public class ParseHtml {
/**
* 微信單頁(yè)面結(jié)構(gòu)解析,這里我們只要將頁(yè)面中的圖片對(duì)應(yīng)的URL取出
* (方法中的解析邏輯是根據(jù)分析頁(yè)面結(jié)構(gòu)和各元素的特征來(lái)解析的)
*
* @param document
* @param urls
*/
public static void singlePageParseImg(Document document, List<String> urls) {
Elements divElements = document.select("[class=rich_media_content]");
Elements pElements = divElements.select("p");
Elements imgElements = pElements.select("img");
for (Element imgElement : imgElements) {
urls.add(imgElement.attr("data-src"));
//打印目標(biāo)數(shù)據(jù)橙困,查看是否正確
}
Elements spanElements = pElements.select("span");
Elements imgElemnets = spanElements.select("img");
for (Element imgElement : imgElemnets) {
urls.add(imgElement.attr("data-src"));
//打印目標(biāo)數(shù)據(jù)瞧掺,查看是否正確
System.out.println(imgElement.attr("data-src"));
}
}
}
4、啟動(dòng)第一個(gè)類(lèi)中的main函數(shù)
查看我們爬取的目標(biāo)圖片是否已經(jīng)存在目錄中凡傅。
總結(jié)
其實(shí)爬蟲(chóng)并不難寫(xiě)辟狈,首先要先知道爬蟲(chóng)是什么東西。爬蟲(chóng)就是使用程序模擬一個(gè)瀏覽器對(duì)頁(yè)面上的數(shù)據(jù)進(jìn)行不斷的連接獲取解析并保存夏跷;這里我只是使用Apache開(kāi)源的成熟框架進(jìn)行開(kāi)發(fā)哼转,實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的單頁(yè)面抓取,同樣的多頁(yè)面循環(huán)抓取就需要在程序中做不斷的迭代槽华,并不斷的更新爬取目標(biāo)壹蔓;即在使用程序解析頁(yè)面的時(shí)候?qū)⑾乱粋€(gè)目標(biāo)頁(yè)的Url保存在待爬取的列表中。
爬蟲(chóng)并不難實(shí)現(xiàn)猫态,難的是對(duì)目標(biāo)頁(yè)面分析佣蓉,找到頁(yè)面中個(gè)元素之間的規(guī)律披摄,對(duì)頁(yè)面進(jìn)行規(guī)律性解析,并獲取到我們想要的數(shù)據(jù)勇凭;當(dāng)然更難的是有些大網(wǎng)站服務(wù)器上的反爬蟲(chóng)機(jī)制疚膊。
接下來(lái)我會(huì)實(shí)現(xiàn)一個(gè)多頁(yè)面循環(huán)抓取的Demo
示例代碼