您好,登錄后才能下訂單哦!
1、需求及配置
需求:爬取京東手機搜索頁面的信息,記錄各手機的名稱,價格,評論數等,形成一個可用于實際分析的數據表格。
使用Maven項目,log4j記錄日志,日志僅導出到控制臺。
Maven依賴如下(pom.xml)
<dependencies> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.3</version> </dependency> <dependency> <!-- jsoup HTML parser library @ https://jsoup.org/ --> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.2</version> </dependency> <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>
log4j配置(log4j.properties),將INFO及以上等級信息輸出到控制臺,不單獨設置輸出文檔。
log4j.rootLogger=INFO, Console #Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
2、需求分析與代碼
2.1需求分析
第一步,建立客戶端與服務端的連接,并通過URL獲得網頁上的HTML內容。
第二步,解析HTML內容,獲取需要的元素。
第三步,將HTML內容輸出到本地的文本文檔中,可直接通過其他數據分析軟件進行分析。
根據以上分析,建立4個類,GetHTML(用于獲取網站HTML), ParseHTML(用于解析HTML), WriteTo(用于輸出文檔), Maincontrol(主控).下面分別對四個類進行說明。為使代碼盡量簡潔,所有的異常均從方法上直接拋出,不catch。
2.2代碼
2.2.1GetHTML類
該類包含兩個方法:getH(String url), urlControl(String baseurl, int page),分別用于獲取網頁HTML及控制URL。由于此次爬取的網頁內容只是京東上某一類商品的搜索結果,所以不需要對頁面上所有的URL進行遍歷,只需要觀察翻頁時URL的變化,推出規律即可。只向外暴露urlControl方法,類中設置一個private的log屬性:private static Logger log = Logger.getLogger(getHTML.class); 用于記錄日志。
getH(String url),對單個URL的HTML內容進行獲取。
urlControl(String baseurl, int page),設置循環,訪問多個頁面的數據。通過審查元素可以看到京東上搜索頁page的變化實際是奇數順序的變化。
再看一下點擊后網址的變化,可以發現實際變化的是page屬性的值。通過拼接的方式就可以很的容易的獲得下一個網頁的地址。
https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&cid2=653&cid3=655&page=3&s=47&click=0
https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&cid2=653&cid3=655&page=5&s=111&click=0
https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&cid2=653&cid3=655&page=7&s=162&click=0
整體代碼:
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; import org.apache.log4j.Logger; public class getHTML { //建立日志 private static Logger log = Logger.getLogger(getHTML.class); private static String getH(String url) throws ClientProtocolException, IOException { //控制臺輸出日志,這樣每條訪問的URL都可以在控制臺上看到訪問情況 log.info("正在解析" + url); /* * 以下內容為HttpClient建立連接的一般用法 * 使用HttpClient建立客戶端 * 使用get方法訪問指定URL * 獲得應答 * */ CloseableHttpClient client = HttpClients.createDefault(); HttpGet get = new HttpGet(url); CloseableHttpResponse response = client.execute(get); /* * 以下內容為將HTML內容轉化為String * 獲得應答體 * 將應答體轉為String格式,此處使用了EntityUtils中的toString方法,編碼格式設置為"utf-8" * 完成后關閉客戶端與應答 * */ HttpEntity entity = response.getEntity(); String content; if (entity != null) { content = EntityUtils.toString(entity, "utf-8"); client.close(); response.close(); return content; } else return null; } public static void urlControl(String baseurl, int page) throws ClientProtocolException, IOException { //設置當前頁count int count = 1; //如果當前頁小于想要爬取的頁數則執行 while (count < page) { //實際訪問的URL為不變的URL值拼接上URL變化的值 String u = baseurl + (2 * count - 1) + "&click=0"; //此處調用ParseHTML類中的方法對URL中的HTML頁面進行處理,后面詳細介紹該類 String content = ParseHTML.parse(getH(u)).toString(); //此處調用WriteTo類中的方法對解析出來的內容寫入到本地,后面詳細介紹該類 WriteTo.writeto(content); count++; } } }
2.2.2ParseHTML類
該步驟需要通過審查元素對需要爬取內容的標簽進行確定,再通過Jsoup中的CSS選擇器進行獲取。
import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; public class ParseHTML { public static StringBuilder parse(String content) { //使用Jsoup中的parse方法對已經轉換為String的HTML內容進行分析,返回值為Document類 Document doc = Jsoup.parse(content); //使用選擇器select對需要找的元素進行抓取,例如第一個select中選擇的是ul標簽中class屬性等于gl-warp clearfix的內容 Elements ele = doc.select("ul[class = gl-warp clearfix]").select("li[class=gl-item]"); //設置一個容器,用于裝各個屬性 StringBuilder sb = new StringBuilder(); //通過上一個選擇器可以獲得整個頁面中所有符合要求的元素,也即各款手機,下面則需要對每款手機進行遍歷,獲取其屬性 for (Element e : ele) { //此處對各個屬性的獲取參考了網上一篇爬取京東上內容的文章,應該有其他不同的寫法 String id = e.attr("data-pid"); String mingzi = e.select("div[class = p-name p-name-type-2]").select("a").select("em").text(); String jiage = e.select("div[class=p-price]").select("strong").select("i").text(); String pinglun = e.select("div[class=p-commit]").select("strong").select("a").text(); //向容器中添加屬性 sb.append(id+"\t"); sb.append(mingzi+"\t"); sb.append(jiage+"\t"); sb.append(pinglun+"\t"); sb.append("\r\n"); } return sb; } }
2.2.3WriteTo類
此類中的方法將解析完成的內容寫入到一個本地文件中。只是簡單的IO。
import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; public class WriteTo { // 設置文件存放的位置 private static File f = new File("C:\\jingdong.txt"); public static void writeto(String content) throws IOException { //使用續寫的方式,以免覆蓋前面寫入的內容 BufferedWriter bw = new BufferedWriter(new FileWriter(f, true)); bw.append(content); bw.flush(); bw.close(); } }
2.2.4MainControl類
主控程序,寫入基地址與想要獲取的頁面數。調用getHTML類中的urlControl方法對頁面進行抓取。
import java.io.IOException; import org.apache.http.client.ClientProtocolException; public class MainControl { public static void main(String[] args) throws ClientProtocolException, IOException { // TODO Auto-generated method stub String baseurl = "https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=" + "utf-8&qrst=1&rt=1&stop=1&vt=2&cid2=653&cid3=655&page="; int page = 5;//設置爬取頁數 getHTML.urlControl(baseurl, page); } }
3、爬取結果
爬取20頁。
3.1控制臺輸出
3.2文檔輸出
可以直接使用Excel打開,分隔符為制表符。列分別為商品編號,名稱,價格與評論數。
4、小結
此次爬取使用了HttpClient與Jsoup,可以看到對于簡單的需求,這些工具還是非常高效的。實際上也可以把所有類寫到一個類當中,寫多個類的方式思路比較清晰。
以上這篇Java爬蟲實現爬取京東上的手機搜索頁面 HttpCliient+Jsoup就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。