摘要:話題精華即為知乎的高票回答。下面的項(xiàng)目中還包含了另外一個(gè)爬取的知乎的動(dòng)態(tài)。
作者:William
本文為原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明作者及出處
Electron 可以讓你使用純 JavaScript 調(diào)用 Chrome 豐富的原生的接口來(lái)創(chuàng)造桌面應(yīng)用。你可以把它看作一個(gè)專注于桌面應(yīng)用的 Node.js 的變體,而不是 Web 服務(wù)器。其基于瀏覽器的應(yīng)用方式可以極方便的做各種響應(yīng)式的交互,接下來(lái)介紹下關(guān)于 Electron 上衍生出的框架 Nightmare。
Nightmare 是一個(gè)基于 Electron 的框架,針對(duì) Web 自動(dòng)化測(cè)試和爬蟲(chóng)(其實(shí)爬蟲(chóng)這個(gè)是大家自己給這個(gè)框架加的功能XD),因?yàn)槠渚哂懈?PlantomJS 一樣的自動(dòng)化測(cè)試的功能可以在頁(yè)面上模擬用戶的行為觸發(fā)一些異步數(shù)據(jù)加載,也可以跟 Request 庫(kù)一樣直接訪問(wèn) URL 來(lái)抓取數(shù)據(jù),并且可以設(shè)置頁(yè)面的延遲時(shí)間,所以無(wú)論是手動(dòng)觸發(fā)腳本還是行為觸發(fā)腳本都是輕而易舉的(這邊注意,如果事件具備 isTrusted 的檢查的話,就無(wú)法觸發(fā)了)。
使用 Nightmare為了更快速使用 NPM 下載,可以使用淘寶的鏡像地址。直接 NPM 安裝Nightmare 就完成安裝了(二進(jìn)制的 Electron 依賴有點(diǎn)大,安裝時(shí)間可能比較長(zhǎng))。
寫(xiě)一個(gè)簡(jiǎn)單的啟動(dòng) app.js;
const Nightmare = require("nightmare") const nightmare = new Nightmare({ show: true, openDevTools: { mode: "detach" } }) nightmare.goto("https://www.hujiang.com") .evaluate(function() { // 該環(huán)境中能使用瀏覽器中的任何對(duì)象window/document,并且返回一個(gè)promise console.log("hello nightmare") console.log("5 second close window") }) .wait(5000) .end() .then(()=> { console.log("close nightmare") })
這個(gè)腳本會(huì)在打開(kāi)的瀏覽器的調(diào)試控制臺(tái)中打印出 hello nightmare 并且在5秒后關(guān)閉,隨后在運(yùn)行的該腳本的中輸出 close nightmare。
Nightmare原理利用了 Electron 提供的 Browser 的環(huán)境,同時(shí)具備了 Node.js 的 I/O 能力,所以可以很方便實(shí)現(xiàn)一個(gè)爬蟲(chóng)應(yīng)用。Nightmare 的官網(wǎng)有更詳細(xì)的介紹:
大致操作:
瀏覽器事件: goto,back,forward,refresh,
用戶事件: click,mousedown,mouseup,mouseover,type,insert,select,check,uncheck,selectscrollTo
向網(wǎng)頁(yè)注入腳本: .js .css的文件類型原理是跟油猴差不多,可以編寫(xiě)自己的js代碼注入十分方便
wait 函數(shù)可以按照延遲時(shí)間或者一個(gè) dom 元素的出現(xiàn)
evaluate 以瀏覽器的環(huán)境運(yùn)行的腳本函數(shù),然后返回一個(gè) promise 函數(shù)
一個(gè)完整的nightmare爬蟲(chóng)應(yīng)用我們以抓取知乎上的話題的為應(yīng)用場(chǎng)景,需要的數(shù)據(jù)是知乎的話題信息 包含以下字段 話題名稱/話題的圖片/關(guān)注者數(shù)量/話題數(shù)量/精華話題數(shù)量,但是因?yàn)楹笕咧荒茉谄涓赣H話題中包含,所以必須先抓父話題才能抓取子話題,而且這些子話題是以 hover 的形式在父話題中異步加載的,如果用Request/Superagent 需要 HTTP 傳遞其解析過(guò)的id才能獲取,但是用Nightmare 可以直接調(diào)用其 hover 事件觸發(fā)數(shù)據(jù)的加載。
第一步獲取需要抓取的話題深度,默認(rèn)的根是現(xiàn)在知乎的根話題;
/** * 抓取對(duì)應(yīng)的話題頁(yè)面的url和對(duì)應(yīng)的深度保存到指定的文件名中 * @param {string} rootUrl - 頂層的url * @param {int} deep - 抓取頁(yè)面的深度 * @param {string} toFile - 保存的文件名 * @param {Function} cb - 完成后的回調(diào) */ async function crawlerTopicsFromRoot (rootUrl, deep, toFile, cb) { rootUrl = rootUrl ||"https://www.zhihu.com/topic/19776749/hot" toFile = toFile || "./topicsTree.json" console.time() const result = await interactive .iAllTopics(rootUrl, deep) console.timeEnd() util.writeJSONToFile(result["topics"], toFile, cb) } crawlerTopicsFromRoot("", 2, "", _ => { console.log("完成抓取") })
然后進(jìn)行交互函數(shù)的核心函數(shù),注意在開(kāi)始抓取前,要去看看知乎的 robots.txt 文件看看哪些能抓和抓取的間隔不然很容易 timeout 的錯(cuò)誤。
// 獲取對(duì)應(yīng)的話題的信息 const cntObj = queue.shift() const url = `https://www.zhihu.com/topic/${cntObj["id"]}/hot` const topicOriginalInfo = await nightmare .goto(url) .wait(".zu-main-sidebar") // 等待該元素的出現(xiàn) .evaluate(function () { // 獲取這塊數(shù)據(jù) return document.querySelector(".zu-main-sidebar").innerHTML }) // .....若干步的操作后 // 獲取其子話題的數(shù)值信息 const hoverElement = `a.zm-item-tag[href$="${childTopics[i]["id"]}"]` const waitElement = `.avatar-link[href$="${childTopics[i]["id"]}"]` const topicAttached = await nightmare .mouseover(hoverElement) // 觸發(fā)hover事件 .wait(waitElement) .evaluate(function () { return document.querySelector(".zh-profile-card").innerHTML }) .then(val => { return parseRule.crawlerTopicNumbericalAttr(val) }) .catch(error => { console.error(error) })
cheerio 是一個(gè) jQuery 的 selector 庫(kù),可以應(yīng)用于 HTML 片段并且獲得對(duì)應(yīng)的DOM 元素,然后我們就可以進(jìn)行對(duì)應(yīng)的 DOM 操作->增刪改查都可以,這邊主要用來(lái)查詢 DOM 和獲取數(shù)據(jù)。
const $ = require("cheerio") /** *抓取對(duì)應(yīng)話題的問(wèn)題數(shù)量/精華話題數(shù)量/關(guān)注者數(shù)量 */ const crawlerTopicNumbericalAttr = function (html) { const $ = cheerio.load(html) const keys = ["questions", "top-answers", "followers"] const obj = {} obj["avatar"] = $(".Avatar.Avatar--xs").attr("src") keys.forEach(key => { obj[key] = ($(`div.meta a.item[href$=${key}] .value`).text() || "").trim() }) return obj } /** * 抓取話題的信息 */ const crawlerTopics = function (html) { const $ = cheerio.load(html) const obj = {} const childTopics = crawlerAttachTopic($, ".child-topic") obj["desc"] = $("div.zm-editable-content").text() || "" if (childTopics.length > 0) { obj["childTopics"] = childTopics } return obj } /** * 抓取子話題的信息id/名稱 */ const crawlerAttachTopic = function ($, selector) { const topicsSet = [] $(selector).find(".zm-item-tag").each((index, elm) => { const self = $(elm) const topic = {} topic["id"] = self.attr("data-token") topic["value"] = self.text().trim() topicsSet.push(topic) }) return topicsSet }
然后一個(gè)簡(jiǎn)單的爬蟲(chóng)就完成了,最終獲得部分?jǐn)?shù)據(jù)格式如何:
{ "value": "rootValue", "id": "19776749", "fatherId": "-1", "desc": "知乎的全部話題通過(guò)父子關(guān)系構(gòu)成一個(gè)有根無(wú)循環(huán)的有向圖。「根話題」即為所有話題的最上層的父話題。話題精華即為知乎的 Top1000 高票回答。請(qǐng)不要在問(wèn)題上直接綁定「根話題」。這樣會(huì)使問(wèn)題話題過(guò)于寬泛。", "cids": [ "19778317", "19776751", "19778298", "19618774", "19778287", "19560891" ] }, { "id": "19778317", "value": "生活、藝術(shù)、文化與活動(dòng)", "avatar": "https://pic4.zhimg.com/6df49c633_xs.jpg", "questions": "3.7M", "top-answers": "1000", "followers": "91K", "fid": "19776749", "desc": "以人類集體行為和人類社會(huì)文明為主體的話題,其內(nèi)容主要包含生活、藝術(shù)、文化、活動(dòng)四個(gè)方面。", "cids": [ "19551147", "19554825", "19550453", "19552706", "19551077", "19550434", "19552266", "19554791", "19553622", "19553632" ] },總結(jié)
Nightmare 作為爬蟲(chóng)的最大優(yōu)勢(shì)是只需要知道數(shù)據(jù)所在頁(yè)面的 URL 就可以獲取對(duì)應(yīng)的同步/異步數(shù)據(jù),并不需要詳細(xì)的分析 HTTP 需要傳遞的參數(shù)。只需要知道進(jìn)行哪些操作能使得網(wǎng)頁(yè)頁(yè)面數(shù)據(jù)更新,就能通過(guò)獲取更新后的 HTML 片段獲得對(duì)應(yīng)的數(shù)據(jù),在 Demo 中的 Nightmare 是打開(kāi)了 chrome-dev 進(jìn)行操作的,但是實(shí)際運(yùn)行的時(shí)候是可以關(guān)閉的,關(guān)閉了之后其操作的速度會(huì)有一定的上升。下面的項(xiàng)目中還包含了另外一個(gè)爬取的知乎的動(dòng)態(tài)。
Demo源碼地址: https://github.com/williamsta...
iKcamp原創(chuàng)新書(shū)《移動(dòng)Web前端高效開(kāi)發(fā)實(shí)戰(zhàn)》已在亞馬遜、京東、當(dāng)當(dāng)開(kāi)售。
>> 滬江Web前端上海團(tuán)隊(duì)招聘【W(wǎng)eb前端架構(gòu)師】,有意者簡(jiǎn)歷至:zhouyao@hujiang.com <<
報(bào)名地址:http://www.huodongxing.com/ev...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/91739.html
摘要:項(xiàng)目背景龐大的用戶安裝量和恐怖的用戶使用時(shí)間,微信已成為國(guó)內(nèi)移動(dòng)互聯(lián)網(wǎng)上基礎(chǔ)設(shè)施級(jí)的應(yīng)用。以一周時(shí)間開(kāi)發(fā)的微信天氣查詢助手,就是一次技術(shù)驗(yàn)證性嘗試。但就針對(duì)微信來(lái)說(shuō),不是最好的解決方案。 項(xiàng)目背景 龐大的用戶安裝量和恐怖的用戶使用時(shí)間,微信已成為國(guó)內(nèi)移動(dòng)互聯(lián)網(wǎng)上基礎(chǔ)設(shè)施級(jí)的應(yīng)用。 以微信為平臺(tái)的客服服務(wù)有很多方式,比如訂閱號(hào),服務(wù)號(hào),小程序,但受到微信官方的限制,如果想做一個(gè)聊天群的自...
摘要:爬蟲(chóng)介紹二爬蟲(chóng)的分類通用網(wǎng)絡(luò)爬蟲(chóng)全網(wǎng)爬蟲(chóng)爬行對(duì)象從一些種子擴(kuò)充到整個(gè),主要為門(mén)戶站點(diǎn)搜索引擎和大型服務(wù)提供商采集數(shù)據(jù)。 分分鐘教你用node.js寫(xiě)個(gè)爬蟲(chóng) 寫(xiě)在前面 十分感謝大家的點(diǎn)贊和關(guān)注。其實(shí),這是我第一次在segmentfault上寫(xiě)文章。因?yàn)槲乙彩乔岸螘r(shí)間偶然之間才開(kāi)始了解和學(xué)習(xí)爬蟲(chóng),而且學(xué)習(xí)node的時(shí)間也不是很長(zhǎng)。雖然用node做過(guò)一些后端的項(xiàng)目,但其實(shí)在node和爬蟲(chóng)方面...
摘要:測(cè)試框架通常提供測(cè)試驅(qū)動(dòng)開(kāi)發(fā)或行為驅(qū)動(dòng)開(kāi)發(fā)的測(cè)試語(yǔ)法來(lái)編寫(xiě)測(cè)試用例。利用上面的工具基本上就可以開(kāi)始進(jìn)行測(cè)試腳本的測(cè)試工作了。下面一篇文章就會(huì)介紹如何使用來(lái)對(duì)應(yīng)用進(jìn)行測(cè)試。 部分基本概念及內(nèi)容: 單元測(cè)試: 以模塊為單元,測(cè)試你代碼的本身,確保你編寫(xiě)的模塊還有邏輯正確。只要輸入的值不變,輸出的值也應(yīng)該不發(fā)生改變 前端自動(dòng)化測(cè)試: 界面回歸測(cè)試 測(cè)試界面是否正常,包括文案,圖片等。 功能...
摘要:前端日?qǐng)?bào)精選中的垃圾收集,圖文指南十個(gè)免費(fèi)的前端開(kāi)發(fā)工具專題之遞歸如何在鏈中共享變量基于的爬蟲(chóng)框架中文譯十六進(jìn)制顏色揭秘掘金掘金小書(shū)基本環(huán)境安裝小書(shū)教程中間件對(duì)閉包的一個(gè)巧妙使用簡(jiǎn)書(shū)源碼分析掘金組件開(kāi)發(fā)練習(xí)焦點(diǎn)圖切換前端學(xué) 2017-09-13 前端日?qǐng)?bào) 精選 V8 中的垃圾收集(GC),圖文指南十個(gè)免費(fèi)的web前端開(kāi)發(fā)工具JavaScript專題之遞歸 · Issue #49 · m...
摘要:使用可以快速生成一個(gè)項(xiàng)目,其中包含了和以及覆蓋率統(tǒng)計(jì)的配置參考一個(gè)創(chuàng)建測(cè)試腳本的快速方法其他參考資料前端自動(dòng)化測(cè)試概覽測(cè)試之使用對(duì)項(xiàng)目進(jìn)行單元測(cè)試 showImg(https://segmentfault.com/img/bVbjfXr?w=600&h=317); 前言 測(cè)試可以提供快速反饋,根據(jù)測(cè)試用例覆蓋代碼,從而提升代碼開(kāi)發(fā)效率和質(zhì)量。根據(jù)投入產(chǎn)出價(jià)值,通常迭代較快的業(yè)務(wù)邏輯不做...
閱讀 1760·2023-04-26 00:20
閱讀 1804·2021-11-08 13:21
閱讀 1930·2021-09-10 10:51
閱讀 1557·2021-09-10 10:50
閱讀 3249·2019-08-30 15:54
閱讀 2131·2019-08-30 14:22
閱讀 1429·2019-08-29 16:10
閱讀 3089·2019-08-26 11:50