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