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