soup是一款Java的HTML解析器,可直接解析某個URL地址、HTML文本內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似于jQuery的操作方法來取出和操作數據。
在爬蟲采集網頁領域主要作用是用HttpClient獲取到網頁后,使用Jsoup提取網頁中需要的信息,Jsoup支持類似Jquery、CSS選擇器,來獲取需要的數據,使用非常方便。
下面結合代碼簡單展示如何使用Jsoup獲取需要的頁面數據。
public class JsoupHello {
public static void main(String[] args) throws Exception{
CloseableHttpClient httpclient=HttpClients.createDefault(); // 創建httpclient實例
HttpGet httpget=new HttpGet("http://www.cnblogs.com/"); // 創建httpget實例
CloseableHttpResponse response=httpclient.execute(httpget); // 執行get請求
HttpEntity entity=response.getEntity(); // 獲取返回實體
String content=EntityUtils.toString(entity, "utf-8");
response.close(); // 關閉流和釋放系統資源
Document doc=Jsoup.parse(content); // 解析網頁 得到文檔對象
Elements elements=doc.getElementsByTag("title"); // 獲取tag是title的所有DOM元素
Element element=elements.get(0); // 獲取第1個元素
String title=element.text(); // 返回元素的文本
System.out.println("網頁標題是:"+title);
Element element2=doc.getElementById("site_nav_top"); // 獲取id=site_nav_top的DOM元素
String navTop=element2.text(); // 返回元素的文本
System.out.println("口號:"+navTop);
}
}
1、使用httpClient 獲取網頁2、使用jsoup parse解析網頁,并根據豐富的getElement方法按照不同的屬性獲取元素值
二、常用查找dom元素方法
1、根據標簽名(tagName)查找dom
Elements elements=doc.getElementsByTag("title"); //獲取tag是title的所有dom元素
Element element=elements.get(0); //獲取第一個
System.out.println(element.text());//輸出元素txt值
2、根據元素Id查找
3、根據class 名查找
4、根據attribute屬性名查找
5、根據attribute和attributeValue共同查找
三、使用Jsoup選擇器查找dom元素1、class類選擇器使用
//class 使用. 中間空格
Elements eleLinks=doc.select(".post_item .post_item_body h3 a");
for(Element el:eleLinks)
{
System.out.println(el.text());
}
測試 JavaScript 框架庫 - jQuery
引用 jQuery
如需測試 JavaScript 庫,您需要在網頁中引用它。
為了引用某個庫,請使用 <script> 標簽,其 src 屬性設置為庫的 URL:
引用 jQuery
<!DOCTYPE html>
<html>
<head>
<script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js">
</script>
</head>
<body>
</body>
</html>
jQuery 描述
主要的 jQuery 函數是 $() 函數(jQuery 函數)。如果您向該函數傳遞 DOM 對象,它會返回 jQuery 對象,帶有向其添加的 jQuery 功能。
jQuery 允許您通過 CSS 選擇器來選取元素。
在 JavaScript 中,您可以分配一個函數以處理窗口加載事件:
JavaScript 方式:
function myFunction()
{
var obj=document.getElementById("h01");
obj.innerHTML="Hello jQuery";
}
onload=myFunction;
等價的 jQuery 是不同的:
jQuery 方式:
function myFunction()
{
$("#h01").html("Hello jQuery");
}
$(document).ready(myFunction);
上面代碼的最后一行,HTML DOM 文檔對象被傳遞到 jQuery :$(document)。
當您向 jQuery 傳遞 DOM 對象時,jQuery 會返回以 HTML DOM 對象包裝的 jQuery 對象。
jQuery 函數會返回新的 jQuery 對象,其中的 ready() 是一個方法。
由于在 JavaScript 中函數就是變量,因此可以把 myFunction 作為變量傳遞給 jQuery 的 ready 方法。
jQuery 返回 jQuery 對象,與已傳遞的 DOM 對象不同。jQuery 對象擁有的屬性和方法,與 DOM 對象的不同。您不能在 jQuery 對象上使用 HTML DOM 的屬性和方法。 |
測試 jQuery
請試一下下面這個例子:
實例
<!DOCTYPE html>
<html>
<head>
<script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js">
</script>
<script>
function myFunction()
{
$("#h01").html("Hello jQuery")
}
$(document).ready(myFunction);
</script>
</head>
<body>
<h1 id="h01"></h1>
</body>
</html>
請再試一下這個例子:
實例
<!DOCTYPE html>
<html>
<head>
<script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js">
</script>
<script>
function myFunction()
{
$("#h01").attr("style","color:red").html("Hello jQuery")
}
$(document).ready(myFunction);
</script>
</head>
<body>
<h1 id="h01"></h1>
</body>
</html>
正如您在上面的例子中看到的,jQuery 允許鏈接(鏈式語法)。
鏈接(Chaining)是一種在同一對象上執行多個任務的便捷方法。
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
比Python,JavaScript才是更適合寫爬蟲的語言。原因有如下三個方面:
一、任務:爬取用戶在Github上的repo信息
通過實例的方式學習爬蟲是最好的方法,先定一個小目標:爬取github repo信息。入口URL如下,我們只需要一直點擊next按鈕就能夠遍歷到用戶的所有repo。
https://github.com/{{username}}?tab=repositories
獲取repo之后,可以做什么?
二、爬蟲雙股劍:axios和jQuery
axios是JavaScript中很常用的異步網絡請求庫,相比jQuery,它更輕量、更專業。既能夠用于瀏覽器端,也可以用于Node。它的語法風格是promise形式的。在本任務中,只需要了解如下用法就足夠了:
axios.get(url).then((resp)=> { 請求成功,處理resp.data中的html數據 }).catch((err)=> { 請求失敗,錯誤處理 })
請求之后需要處理回復結果,處理回復結果的庫當然是用jQuery。實際上,我們有更好的選擇:cheerio。
在node下,使用jQuery,需要使用jsdom庫模擬一個window對象,這種方法效率較低,四個字形容就是:笨重穩妥。
如下代碼使用jQuery解析haha.html文件
fs=require("fs") jquery=require('jquery') jsdom=require('jsdom') //fs.readFileSync()返回結果是一個buffer,相當于byte[] html=fs.readFileSync('haha.html').toString('utf8') dom=new jsdom.JSDOM(html) $=jquery(dom.window) console.log($('h1'))
cheerio只實現了jQuery中的DOM部分,相當于jQuery的一個子集。cheerio的語法和jQuery完全一致,在使用cheerio時,幾乎感覺不到它和jQuery的差異。在解析HTML方面,毫無疑問,cheerio是更好的選擇。如下代碼使用cheerio解析haha.html文件。
cheerio=require('cheerio') html=require('fs').readFileSync("haha.html").toString('utf8') $=cheerio.load(html) console.log($('h1'))
只需20余行,便可實現簡單的github爬蟲,此爬蟲只爬取了一頁repo列表。
var axios=require("axios") var cheerio=require("cheerio") axios.get("https://github.com/weiyinfu?tab=repositories").then(resp=> { var $=cheerio.load(resp.data) var lis=$("#user-repositories-list li") var repos=[] for (var i=0; i < lis.length; i++) { var li=lis.eq(i) var repo={ repoName: li.find("h3").text().trim(), repoUrl: li.find("h3 a").attr("href").trim(), repoDesc: li.find("p").text().trim(), language: li.find("[itemprop=programmingLanguage]").text().trim(), star: li.find(".muted-link.mr-3").eq(0).text().trim(), fork: li.find(".muted-link.mr-3").eq(1).text().trim(), forkedFrom: li.find(".f6.text-gray.mb-1 a").text().trim() } repos.push(repo) } console.log(repos) })
三、更豐富的功能
爬蟲不是目的,而是達成目的的一種手段。獲取數據也不是目的,從數據中提取統計信息并呈現給人才是最終目的。
在github爬蟲的基礎上,我們可以擴展出更加豐富的功能:使用echarts等圖表展示結果。
要想讓更多人使用此爬蟲工具獲取自己的github統計信息,就需要將做成一個網站的形式,通過搜索頁面輸入用戶名,啟動爬蟲立即爬取github信息,然后使用echarts進行統計展示。網站肯定也要用js作為后端,這樣才能和js爬蟲無縫銜接,不然還要考慮跨語言調用。js后端有兩大web框架express和koa,二者API非常相似,并無優劣之分,但express更加流行。
如上設計有一處用戶體驗不佳的地方:當啟動爬蟲爬取github信息時,用戶可能需要等待好幾秒,這個過程不能讓用戶干等著。一種解決思路是:讓用戶看到爬蟲爬取的進度或者爬取過程。可以通過websocket向用戶推送爬取過程信息并在前端進行展示。展示時,使用類似控制臺的界面進行展示。
如何存儲爬取到的數據呢?使用MongoDB或者文件都可以,最好實現兩種存儲方式,讓系統的存儲方式變得可配置。使用MongoDB時,用到js中的連接池框架generic-pool。
整個項目用到的庫包括:
試用地址:
https://weiyinfu.cn/githubstatistic/search.html?
案例地址:https://github.com/weiyinfu/GithubStatistic
原文鏈接:https://zhuanlan.zhihu.com/p/53763115
*請認真填寫需求信息,我們會在24小時內與您取得聯系。