考慮到這裏有不少人沒有接觸過Java網絡爬蟲,因此我會從很基礎的Jsoup分析HttpClient獲取的網頁講起。瞭解這些東西能夠直接看後面的「正式進入案例」,跳過前面這些基礎。我導入的是「Excel轉換工具XXL-EXCEL」這個開源項目而後在這個基礎上寫的這個Demo(下面會詳細分析).看了這篇文章還有問題,記得給我留言我會盡力幫你解決。若是文章哪裏有問題或者須要改進,也請留言告訴我,共同進步。html
幾天前用HttpClien+Jsoup把網易雲音樂的民謠抓取下來,惋惜顯示效果是下面這樣的: java
想着若是能像前幾天用開源的爬蟲爬取知乎後而後導入Excel簡單分析也好一點,以下圖(下圖只是簡單的對導入進去的一我的的關注者作了一個排序): 經過查閱文檔知道Apache下有一個專門操做office各類文檔的API: POI,用這個API的話操做起來原理也很簡單,可是很麻煩須要寫不少代碼,並且條理也不是很清楚。因此去Github上找了找有沒有更方便的方法,Github有不少關於這方面的開源項目,通過各類嘗試,最終選擇了: 《Java對象和Excel轉換工具XXL-EXCEL》,經過這個框架能夠靈活的進行Java對象和Excel文檔相互轉換。而後最終就是下面這個效果: node
Maven依賴:git
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.7.2</version>
</dependency>
複製代碼
請求網頁和解析網頁,咱們都以推酷網:www.tuicool.com/爲例子。 先看一個實例(本實例獲取的是推酷網首頁的熱門文章的信息):github
package news;
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class TuicoolHotArticles {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String url = "https://www.tuicool.com/";
Document document = Jsoup.connect(url)
.userAgent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0").get();
// #id: 經過ID查找元素,好比:#logo
Elements items = document.select(".list_article_item ");
System.out.println(items.size());
for (Element item : items) {
// 標題。(類名title下的 a標籤的title屬性獲取)
String title = item.select(".title a").attr("title");
// 標題圖片地址(類名article_thumb_image下的 img標籤的src屬性獲取)
String picture_href = item.select(".article_thumb_image img").attr("src");
// 時間 。(類名tip下的最後一個span標籤的文字獲取)
String date = item.select(".tip span").last().text();
// 做者 。(類名tip下的第一個span標籤的文字獲取)
String author = item.select(".tip span").first().text();
System.out.println("標題: " + title);
System.out.println("標題圖片地址:" + picture_href);
System.out.println("發佈日期 " + date);
System.out.println("做者 " + author);
System.out.println();
System.out.println();
}
}
}
複製代碼
實例結果: apache
實例分析:元素位置->右鍵->查看元素(Inspent Element) 瀏覽器
2. Jsoup解析 經過元素分析咱們便可獲取所在div類名以及元素的其餘屬性,經過這些屬性咱們便可獲取該元素。上面代碼我已經給你詳細的註釋,若是還有問題能夠留言給我。若是想了解更詳細的Jsoup操做請查看 jsoup中文文檔。bash
Maven依賴:網絡
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.4</version>
</dependency>
複製代碼
下面是一個獲取推酷首頁源代碼的例子:app
package www.java1234.com.httpclientDemo2;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
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.apache.http.util.EntityUtils;
/** * TODO 在www.java1234.com.httpclientDemo.HelloWorld2咱們獲取推酷網熱門文章 * 咱們這裏經過模擬瀏覽器的方法來從新獲取 * * @date 2017年12月16日 */
public class GetTuicoolHotArticles {
public static void main(String[] args) throws ClientProtocolException, IOException {
// TODO Auto-generated method stub
CloseableHttpClient httpClient = HttpClients.createDefault(); // 建立httpClient實例
HttpGet httpGet = new HttpGet("https://www.tuicool.com/"); // 建立httpget實例
// 設置請求頭信息Uer-Agent模擬瀏覽器
httpGet.setHeader("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0");
CloseableHttpResponse response = httpClient.execute(httpGet); // 執行httpget請求
// 獲取響應狀態
//System.out.println("響應狀態爲:" + response.getStatusLine());
HttpEntity entity = response.getEntity(); // 獲取返回實體
System.out.println("網頁內容:" + EntityUtils.toString(entity, "utf-8"));
// 獲取響應內容類型Content-Type
// System.out.println("content-type:" + entity.getContentType());
response.close(); // response關閉
httpClient.close(); // httpClient關閉
}
}
複製代碼
這個例子有一點須要說明的是由於推酷網設置了簡單的反爬因此咱們這裏必須設置請求頭信息Uer-Agent模擬瀏覽器訪問,代碼已經註釋。
若是想深刻學習HttpClient,請查看HttpClient官網。
網上有不少這面的教程,並且Maven這個工具真的很實用,不會的能夠在網上找一找教程。再不會留言找我,我教,😁嘿嘿。
完整源碼下載:github.com/Snailclimb/… XXL-EXCEL的Maven依賴
<!-- http://repo1.maven.org/maven2/com/xuxueli/xxl-excel-core/ -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-excel</artifactId>
<version>1.0.0</version>
</dependency>
複製代碼
我一共新建了三個類:
Wangyiyun.java:網易雲音樂實體類。WangyiyunMinyao.java:網易雲音樂工具類,用於獲取存放歌曲對象打得Arraylist集合。
TestWangyiyun.java:測試類,測試獲取網易雲音樂民謠信息而且輸出到Excel中。 由於一次抓取的是一個頁面,因此抓取到控制檯有輸出,速度可能有點慢。 Wangyiyun.java
package com.xuxueli.poi.excel.test.model;
import org.apache.poi.hssf.util.HSSFColor;
import com.xuxueli.poi.excel.annotation.ExcelField;
import com.xuxueli.poi.excel.annotation.ExcelSheet;
@ExcelSheet(name = "網易雲音樂民謠分析", headColor = HSSFColor.HSSFColorPredefined.LIGHT_GREEN)
public class Wangyiyun {
@ExcelField(name = "歌曲介紹")
private String description;
@ExcelField(name = "歌曲連接地址")
private String href;
@ExcelField(name = "歌曲播放次數")
private int playNums;
public Wangyiyun() {
}
public Wangyiyun(String description, String href, int playNums) {
this.description = description;
this.href = href;
this.playNums = playNums;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
public int getPlayNums() {
return playNums;
}
public void setPlayNums(int playNums) {
this.playNums = playNums;
}
@Override
public String toString() {
return "Wangyiyun [歌曲介紹=" + description + ", 歌曲連接地址=" + href + ", 歌曲播放次數=" + playNums + "]";
}
}
複製代碼
WangyiyunMinyao.java
package utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
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 org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import com.xuxueli.poi.excel.test.model.Wangyiyun;
/** * TODO 該類用於獲取保存在Arraylist中的歌曲對象 * @date 2017年12月21日 */
public class WangyiyunMinyao {
/** * 該方法爬取了歌曲標題和連接地址而且調用了GetTheNumberOfPlays()方法用於獲取歌曲連接地址頁面的詳細播放次數 * * @param url_str * @param charset * @throws ClientProtocolException * @throws IOException */
public static ArrayList<Wangyiyun> Crawl(String url_str, String charset) throws ClientProtocolException, IOException {
// 獲取
CloseableHttpClient hc=HttpClients.createDefault();
//HttpClient hc = new DefaultHttpClient();
HttpGet hg = new HttpGet(url_str);
HttpResponse response = hc.execute(hg);
HttpEntity entity = response.getEntity();
InputStream htm_in = null;
ArrayList<Wangyiyun> arrayList = new ArrayList<>();
if (entity != null) {
htm_in = entity.getContent();
String htm_str = InputStream2String(htm_in, charset);
Document doc = Jsoup.parse(htm_str);
Elements links = doc.select("div[class=g-bd]").select("div[class=g-wrap p-pl f-pr]")
.select("ul[class=m-cvrlst f-cb]").select("div[class=u-cover u-cover-1");
for (Element link : links) {
Elements lin = link.select("a");
// 歌曲描述
String description = lin.attr("title");
// 歌曲連接地址
String href = lin.attr("href");
href = "http://music.163.com" + href;
/* * System.out.print(re_title + " "); * System.out.print(re_url + " "); int nums = * GetTheNumberOfPlays(re_url, charset); */
int nums =GetTheNumberOfPlays(href, charset);
Wangyiyun wangyiyun = new Wangyiyun(description, href, nums);
arrayList.add(wangyiyun);
}
}
return arrayList;
}
/** * 該方法爬取歌曲連接地址頁面的播放次數 * * @param url_str * @param charset * @throws ClientProtocolException * @throws IOExceptionGet * the number of plays */
public static int GetTheNumberOfPlays(String url_str, String charset) throws ClientProtocolException, IOException {
CloseableHttpClient hc=HttpClients.createDefault();
HttpGet hg = new HttpGet(url_str);
HttpResponse response = hc.execute(hg);
HttpEntity entity = response.getEntity();
InputStream htm_in = null;
int nums = 0;
if (entity != null) {
htm_in = entity.getContent();
String htm_str = InputStream2String(htm_in, charset);
Document doc = Jsoup.parse(htm_str);
String links = doc.select("div[class=u-title u-title-1 f-cb]").select("div[class=more s-fc3]")
.select("strong").text();
nums = Integer.parseInt(links);
}
return nums;
}
/* * public static void saveHtml(String filepath, String str) { * * try { OutputStreamWriter outs = new OutputStreamWriter(new * FileOutputStream(filepath, true), "utf-8"); * outs.write("http://www.dailystrength.org" + str + "\r\n"); outs.close(); * } catch (IOException e) { System.out.println("Error at save html..."); * System.out.println(str); e.printStackTrace(); } } */
public static String InputStream2String(InputStream in_st, String charset) throws IOException {
BufferedReader buff = new BufferedReader(new InputStreamReader(in_st, charset));
StringBuffer res = new StringBuffer();
String line = "";
while ((line = buff.readLine()) != null) {
res.append(line);
}
return res.toString();
}
}
複製代碼
TestWangyiyun.java
package com.xuxueli.poi.excel.test;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.http.client.ClientProtocolException;
import com.xuxueli.poi.excel.ExcelExportUtil;
import com.xuxueli.poi.excel.test.model.Wangyiyun;
import utils.WangyiyunMinyao;
public class TestWangyiyun {
public static void main(String[] args) throws ClientProtocolException, IOException {
int page = 0;
// 這裏只爬取了3頁數據
ArrayList<Wangyiyun> wangyiyunArraylist=new ArrayList<>();
for (int i = 0; i < 3; i++) {
// 爬取
String url_str = "http://music.163.com/discover/playlist/?order=hot&cat=民謠&limit=35&offset=" + page;
ArrayList<Wangyiyun> arrayList = WangyiyunMinyao.Crawl(url_str, "utf-8");
wangyiyunArraylist.addAll(arrayList);
for (Wangyiyun wangyiyun : arrayList) {
System.out.println(wangyiyun);
}
/**
* Excel導出:Object 轉換爲 Excel
*/
// page參數加35(這個35是分析民謠欄)
page = page + 35;
}
String filePath = "wangyiyun.xls";
ExcelExportUtil.exportToFile(filePath, wangyiyunArraylist, wangyiyunArraylist);
}
}
複製代碼
導入Maven依賴或者導入個人Maven項目後項目上會有感嘆號,這種狀況應該是Jar包下載出錯。(筆主在這裏卡了很長時間)
解決辦法:
查看錯誤->找到出錯的Jar->找到對應jar包存放位置->刪除該jar包->去官網本身下載。剛纔知道你們可能由於jar包下載錯誤或者各類問題有問題。 下面是個人項目的效果圖。目前已經更新到Github。實在還有問題的能夠把個人項目拷貝下來看看。 完整源碼下載:github.com/Snailclimb/…(包含導入Excel的工具源碼)