带你入门Java网络爬虫
文章目錄
- 爬蟲初識
- 選Java還是選Python
- Java網絡爬蟲來了
- 網絡爬蟲流程
- 需要掌握的Java基礎知識
- HTTP協議基礎與網絡抓包
- 小工具實現數據采集
- 文本類數據采集
- 圖片數據的采集
- 大文件內容獲取問題
- 其他知識點
爬蟲初識
記得,在本科時,因為畢業論文需要不少網絡上用戶的問答數據。最開始,我并沒有搞過網絡爬蟲,只能利用關鍵詞搜索的方式,找到相關的數據,然后一條一條復制。你可能覺得這樣很傻,但不得不承認這確實我最初的操作方式,很艱難,累的手疼。
后來,讀研究生時,既要開展實際的項目,同時也要做科研。項目和科研,都需要采集大量的網絡數據。領頭做項目的師兄,指定了一系列國內外網站,并把采集任務分配給我。額,當時,對于啥都不咋會的我,只能說“這該咋弄啊?這咋弄啊?。。”。沒辦法,硬著頭皮也要上。
后來,經師兄指點,讓我去學習網路爬蟲,說網路爬蟲可以搞定“我想要的數據”。聽師兄的,不會錯,那就學吧。
選Java還是選Python
決定要用網絡爬蟲去采集數據了,但面臨一個選擇就是:是用Java還是Python寫網絡爬蟲呢?對于一個新手,我看了一些網上的各種對比帖子,各有各的觀點,其中不少說Python上手容易,寫起來方便。但最終我還是選擇了Java,有以下幾點原因:
(1) Java火了很多年,而且依舊很火,其生態也比較完善。目前,很多大公司的系統皆采用Java設計,足以說明其強大之處。把Java學好了,足夠讓我找一份不錯的工作。
(2) Java是復雜一些難一些,但嚴謹規范,對于大型工程,對于大型程序,如果不規范不嚴謹維護豈不容易出問題。
(3) 對網絡爬蟲而言,JAVA中也有很多簡單易用的類庫(如Jsoup、Httpclient等),同時還存在不少易于二次開發的網絡爬蟲框架(Crawler4J、WebMagic等)。
(4) 曾在一個帖子中看到,“世界上99%的人都會選擇一條容易走的大路,因為人都喜歡安逸。這也是人的大腦的思維方式決定的,因為大腦的使命是為了讓你生存,而不是求知。但成功是總是屬于那1%的人,這類人是堅持讓大腦做不愿意做的事的人——求知”。哎,這在我看來,還真有一定的道理。如果勵志想成為一名真正的程序員,建議先學習Java。在此基礎上,如果你對Python感興趣,也是可以快速上手的。
Java網絡爬蟲來了
網絡爬蟲流程
學習網絡爬蟲之前,先看了普通網絡爬蟲大致流程,如下圖所示:
主要包括5個步驟:
需要掌握的Java基礎知識
在使用Java構建網絡爬蟲時,需要掌握很多Java方面的基礎知識。例如,Java中基本的數據類型、Java中的數組操作、判斷語句的使用、集合操作、對象和類的使用、String類的使用、日期和時間的處理、正則表達式的使用、Maven工程的創建、多線程操作、日志的使用等。
看著知識點很多,但如果將其放入到具體的網絡爬蟲實戰項目中去學習,會發現很簡單。下面,我舉兩個例子。
在網絡爬蟲中,我們經常需要將待采集的URL放到集合中,然后循環遍歷集合中的每個URL去采集數據。比如,我們使用Queue集合操作:
另外,在采集數據時,不同網站的時間使用格式可能不同。而不同的時間格式,會為數據存儲以及數據處理帶來一定的困難。例如,下圖為某汽車論壇中時間使用的格式,即“yyyy-MM-dd”和“yyyy-MM-dd HH:mm”兩種類型。
下圖為某新聞網站中的時間使用格式“yyyy-MM-dd HH:mm:ss”。
再如,藝術品網站deviantart(https://www.deviantart.com/enterthespectrum/modals/memberlist/)的時間使用的是UNIX時間戳的形式。
針對汽車論壇中的“yyyy-MM-dd”和“yyyy-MM-dd HH:mm”格式,可以統一轉化成“yyyy-MM-dd HH:mm:ss”格式,以方便數據存儲以及后期數據處理。此時,可以寫個方法將將字符串類型的時間標準化成指定格式的時間。如下程序:
針對UNIX時間戳,可以通過如下方法處理:
//將unix時間戳轉化成指定形式的時間public static String TimeStampToDate(String timestampString, String formats) {Long timestamp = Long.parseLong(timestampString) * 1000;String date = new SimpleDateFormat(formats, Locale.CHINA).format(new Date(timestamp));return date;}HTTP協議基礎與網絡抓包
做網絡爬蟲,還需要了解HTTP協議相關的內容,即要清楚數據是怎么在服務器和客戶端傳輸的。
具體需要了解的內容包括:
在開發網絡爬蟲時,給定 URL,開發者必須清楚客戶端是怎么向服務器發送請求的,以及客戶端請求后服務器返回的數據是什么。只有了解這些內容,開發者才能在程序中拼接URL,針對服務返回的數據類型設計具體的解析策略。因此,網絡抓包是實現網絡爬蟲必不可少的技能之一,也是網絡爬蟲開發的起點。例如,給定下面的URL:
即我想要獲取阿里天池上的數據集介紹的信息:
從上圖中,可以看到共有107頁,點擊第二頁,會發現瀏覽器中的URL變為發生變化。但通過谷歌瀏覽器抓包的方式,會發現數據真實請求的URL。另外從下圖可以看到請求的方式使用的是POST的形式,并且POST提交的參數是以JSON的形式呈現,同時在請求頭中包含x-csrf-token。
另外,通過Preview可以看到網頁數據返回的形式為JSON:
小工具實現數據采集
網絡爬蟲主要涉及的是網頁請求,網頁解析和內容存儲。下面,使用一塊簡單易用的Jsoup工具實現幾個案例數據的采集。
Jsoup是一款基于Java語言的開源項目,主要用于請求URL獲取網頁內容、解析HTML和XML文件。使用Jsoup可以非常輕松的構建一些輕量級網絡爬蟲。
文本類數據采集
要采集的網站地址為:https://www.pythonforbeginners.com/。網站內容如下圖所示:
其中,我們要采集的字段包括:帖子的標題和帖子的簡介。
我們利用網絡抓包的形式發現該網頁返回的數據為HTML格式,如下圖所示。從中可以看到,我們想要的數據都在標簽“li class=‘hentry’”中。
之后,我們需要使用的jar包,即Jsoup。在Eclipse中創建Maven工程,并在工程的pom.xml文件中添加Jsoup對應的dependency:
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup --><dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.11.3</version></dependency>基于此jar包,可以編寫一個請求該網站數據,解析該網站數據的程序,如下:
package com.qian.test;import java.io.IOException; import org.jsoup.Connection; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements;public class Test {public static void main(String[] args) throws IOException {//創建連接---注意這里是HTTPS協議Connection connect = Jsoup.connect("https://www.pythonforbeginners.com/").validateTLSCertificates(false);//請求網頁Document document = connect.get();//解析數據--CSS選擇器Elements elements = document.select("li[class=hentry]");for (Element ele : elements) {String title = ele.select("h2").text();String url = ele.select("h2>a").attr("href");//控制臺輸出的形式---也可以文件流輸出或導入數據庫System.out.println(title + "\t" + url); }} }執行該程序會在控制臺輸出以下內容:
這里需要注意的是,該網站使用的是HTTPS協議,因此需要調用validateTLSCertificates()方法。否則,如果只使用下面的方式請求頁面,則會報錯。
圖片數據的采集
圖片數據是非常常見的一種數據形式。很多做圖片處理的研究者,經常需要采集一些網站上的圖片,下面以Jsoup工具演示如下采集圖片。給定圖片地址:
https://www.makro.co.za/sys-master/images/h98/h64/9152530710558/06cf39e4-7e43-42d4-ab30-72c81ab0e941-qpn13_medium對應的圖片為:
如下為操作程序:
在上述程序中,使用了ignoreContentType()方法,即忽略請求的數據類型。如果狀態碼為200,即響應成功,接著對數據流進行操作,將圖片下載到指定目錄下。執行該程序,可以發現工程的“image/”目錄下成功多了,一張圖片。
大文件內容獲取問題
在采集數據時,經常遇到一些較大的文件,如包含大量文本信息的HTML文件、超過10M的圖片、PDF和ZIP等文件。Jsoup默認情況下最大只能獲取1M的文件。因此,直接使用Jsoup請求包含大量文本信息的HTML文件,將導致獲取的內容不全;請求下載超過1M的圖片和ZIP等文件,將導致文件無法查看或解壓。但在Jsoup中,可以使用maxBodySize(int bytes)設置請求文件大小限制,來避免這種問題的出現。如下網站:
http://poi.mapbar.com/shanghai/F10
該網站中按照A-B-C-D…一直排下去,導致HTML過大。因此需要使用maxBodySize()方法。程序如下所示:
再如,我要請求一個壓縮文件,URL地址為:
https://www-us.apache.org/dist//httpd/httpd-2.4.37.tar.gzJsoup下載httpd-2.4.37.tar.gz文件(8.75M)時,也需要使用maxBodySize()方法,同時用Integer.MAX_VALUE設置的請求文件大小。另外,在請求大文件時,超時時間也需設置的盡量長些。程序如下:
package com.qian.jsoupconnect;import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.Connection.Method; import org.jsoup.Connection.Response; public class JsoupConnectBodySize1 {public static void main(String[] args) throws IOException {String url = "https://www-us.apache.org/dist//httpd/httpd-2.4.37.tar.gz";//超時時間設置長一些,下載大文件Response response = Jsoup.connect(url).timeout(10*60*1000).maxBodySize(Integer.MAX_VALUE).method(Method.GET).ignoreContentType(true).execute();//如果響應成功,則執行下面的操作if (response.statusCode() ==200) {//響應轉化成輸出流BufferedInputStream bufferedInputStream = response.bodyStream();//保存圖片saveFile(bufferedInputStream,"image/httpd-2.4.37.tar.gz");}}/*** 保存文件* @param 輸入流* @param 保存的文件目錄* @throws IOException*/static void saveFile(BufferedInputStream inputStream, String savePath) throws IOException {byte[] buffer = new byte[1024];int len = 0;//創建緩沖流FileOutputStream fileOutStream = new FileOutputStream(new File(savePath));BufferedOutputStream bufferedOut = new BufferedOutputStream(fileOutStream);//圖片寫入while ((len = inputStream.read(buffer, 0, 1024)) != -1) {bufferedOut.write(buffer, 0, len);}//緩沖流釋放與關閉bufferedOut.flush();bufferedOut.close();} }執行該程序,可以發現“image/”目錄下成功下了httpd-2.4.37.tar.gz。
其他知識點
上面,只介紹了Jsoup的一些簡單用法。更多的知識點將涉及到連接超時問題、請求頭添加問題、POST請求問題、代理問題、詳細的HTML/XML數據解析問題。
另外,在Java網絡爬蟲中,還涉及其他網頁請求工具,例如:HttpClient/URLConnection/OkHttp等。
在數據解析方面,還涉及CSS選擇器的使用、Xpath語法的使用、HtmlCleaner和Htmlparser如何解析HTML;XML數據如何解析;JSON校正、GSON和Fastjson的使用等。
在數據存儲方面,還涉及輸入流和輸出流的操作、EXCEL的操作、數據庫的操作等。
另外,在Java中還存在很多優秀的開源的網絡爬蟲框架,如Crawler4J、Webcollector、WebMagic等。
為幫助想要入門Java網絡爬蟲的讀者,這里特意推薦一本書《網絡數據采集技術 Java網絡爬蟲實戰》。
該書的特色包括:
另外,本書適合的讀者包括:
總結
以上是生活随笔為你收集整理的带你入门Java网络爬虫的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RJ45接口
- 下一篇: java文本区背景颜色_Java如何设置