摘要:前面的文章將做爬蟲(chóng)的基礎(chǔ)一直到部署都梳理了一遍,現(xiàn)在來(lái)看一下分布式的處理為什么需要分布式需要抓取的不同數(shù)據(jù)有很多,會(huì)同時(shí)開(kāi)啟無(wú)頭瀏覽器去抓取,然后獲取到數(shù)據(jù)后又無(wú)厘頭的一股腦擠進(jìn)數(shù)據(jù)庫(kù)無(wú)法保證同一時(shí)刻需要的數(shù)據(jù)只有一個(gè)操作在進(jìn)行分布式選擇因
前面的文章將puppeteer做爬蟲(chóng)的基礎(chǔ)一直到部署都梳理了一遍,現(xiàn)在來(lái)看一下分布式的處理 1) 為什么需要分布式
1. 需要抓取的不同數(shù)據(jù)有很多,會(huì)同時(shí)開(kāi)啟無(wú)頭瀏覽器去抓取,然后獲取到數(shù)據(jù)后又無(wú)厘頭的一股腦擠進(jìn)數(shù)據(jù)庫(kù) 2. 無(wú)法保證同一時(shí)刻需要的數(shù)據(jù)只有一個(gè)操作在進(jìn)行2) 分布式選擇
因?yàn)槭褂玫氖莕ode,所以盡可能的尋找node支持的分布式框架3) 銜接之前的 puppeteer進(jìn)階版_爬取書(shū)旗小說(shuō) 文章內(nèi)容,文章只是放了一些主要的代碼,末尾會(huì)附上項(xiàng)目地址,大家可以去擼一擼
ZooKeeper 和 RabbitMQ 的思想百度上有好多說(shuō)明,讀者可以自行搜索作更詳細(xì)的了解
node版的zookeeper
node版的RabbitMQ
發(fā)布者,給書(shū)旗起一個(gè)標(biāo)識(shí)為 37 (channel_id),然后是要抓取書(shū)的書(shū)籍id(channel_book_id)
// 我們以接口的形式接收爬取的參數(shù) // 簡(jiǎn)易版請(qǐng)求(除了接收參數(shù)不做任何處理) -> 發(fā)布者 app.get("/v1.0/grasp_book", (req, res, next) => { // 抓取時(shí)需要的參數(shù) if (!req.query.channel_id && !req.query.channel_book_id) { res.send({ code: 403, msg: "params error" }) return null; } // 發(fā)布者 // 連接rabbitmq amqp.connect("amqp://rabbitmq:[email protected]:5672/").then(function(conn) { return conn.createChannel().then(function(ch) { // 創(chuàng)建 hello 的消息隊(duì)列 var q = "hello"; // 解析為json字符串格式作為傳遞的數(shù)據(jù)格式 var msg = JSON.stringify({ "channel_id": req.query.channel_id, "book_id": req.query.book_id }) // 連接并保持 var ok = ch.assertQueue(q, {durable: true}); return ok.then(function(_qok) { // 發(fā)送數(shù)據(jù)到消費(fèi)者 ch.sendToQueue(q, Buffer.from(msg)); console.log(" [x] Sent "%s"", msg); return ch.close(); }); }).finally(function() { conn.close(); }); }).catch(console.warn); res.send({ code: 200, msg: "success" }); });
命令行啟動(dòng)app.js,發(fā)出請(qǐng)求并查看結(jié)果,{} 里面的就是我們發(fā)送出去的數(shù)據(jù)
消費(fèi)者,接收到發(fā)布者傳遞過(guò)來(lái)的數(shù)據(jù)建立消息隊(duì)列,然后用Zookeeper創(chuàng)建臨時(shí)節(jié)點(diǎn)以保持隊(duì)列依次執(zhí)行
var zookeeper = require("node-zookeeper-client"); // 根據(jù)標(biāo)識(shí)動(dòng)態(tài)引入js文件 function moduleCustomize(channel_id) { return require(`../${channel_id}.js`) } var client = zookeeper.createClient("127.0.0.1:2181"); async function sleep(second) { return new Promise((resolve, reject) => { setTimeout(() => { resolve("sleep") }, second) }) } // 連接_zookeeper client.once("connected", function () { console.log("Connected to the server."); // 建立連接 rabbitmp amqp.connect("amqp://rabbitmq:[email protected]:5672/").then(function(conn) { return conn.createChannel().then(function(ch) { // 與名為 hello(由發(fā)布者創(chuàng)建) 的消息隊(duì)列建立連接 var ok = ch.assertQueue("hello", {durable: true}); // 預(yù)存為1 ok = ok.then(function() { ch.prefetch(1); }); ok = ok.then(function() { // doWork 回調(diào)函數(shù) -> 執(zhí)行接收到數(shù)據(jù)后的操作 ch.consume("hello", doWork, {noAck: false}); }); return ok; // rabbitmq 處理 function doWork(msg) { // 接收到數(shù)據(jù) var body = msg.content.toString(); console.log("[x] Received "%s"", body); let _body = JSON.parse(body) let channel_book_id = _body["channel_book_id"]; let channel_id = _body["channel_id"]; // zookeeper 節(jié)點(diǎn) let path = `/${channel_id + "_" + channel_book_id}` // 連接_zookeeper 判斷是否存在 client.exists(path, function (error, stat) { if (error) { console.log(error.stack); return; } if (stat) { console.log("Node exists."); // 存在則不執(zhí)行,但需要將數(shù)據(jù)傳遞下去 // ack 可以參考 https://www.jianshu.com/p/a5f7fce67803 ch.ack(msg); } else { console.log("Node does not exist."); // 操作完成后則釋放當(dāng)前創(chuàng)建的臨時(shí)節(jié)點(diǎn) client.create(path, null, zookeeper.CreateMode.EPHEMERAL, function (error) { if (error) { console.log("Failed to create node: %s due to: %s.", path, error); } else { console.log("Node: %s is successfully created.", path); // 根據(jù)傳入標(biāo)識(shí)(如書(shū)旗就是37)動(dòng)態(tài)引入js文件(抓書(shū)的操作) moduleCustomize(channel_id).init(channel_book_id) // 傳遞數(shù)據(jù) ch.ack(msg); // 釋放當(dāng)前創(chuàng)建的臨時(shí)節(jié)點(diǎn) client.remove(path, -1, function (error) { if (error) { console.log(error.stack); return; } console.log("Node is deleted."); }); } }); } console.log("任務(wù)執(zhí)行完畢") }); } }); }).catch(console.warn); }); client.connect();
命令行啟動(dòng)rab_consumer.js,{} 里面就是我們接收到消息隊(duì)列里面的數(shù)據(jù)了4) 查看mongo結(jié)果數(shù)據(jù) 5) 項(xiàng)目地址(update分支)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93256.html
摘要:爬蟲(chóng)是我接觸計(jì)算機(jī)編程的入門(mén)。練練練本文推薦的資源就是以項(xiàng)目練習(xí)帶動(dòng)爬蟲(chóng)學(xué)習(xí),囊括了大部分爬蟲(chóng)工程師要求的知識(shí)點(diǎn)。拓展閱讀一文了解爬蟲(chóng)與反爬蟲(chóng)最后,請(qǐng)注意,爬蟲(chóng)的工作機(jī)會(huì)相對(duì)較少。 爬蟲(chóng)是我接觸計(jì)算機(jī)編程的入門(mén)。哥當(dāng)年寫(xiě)第一行代碼的時(shí)候別提有多痛苦。 本文旨在用一篇文章說(shuō)透爬蟲(chóng)如何自學(xué)可以達(dá)到找工作的要求。 爬蟲(chóng)的學(xué)習(xí)就是跟著實(shí)際項(xiàng)目去學(xué),每個(gè)項(xiàng)目會(huì)涉及到不同的知識(shí)點(diǎn),項(xiàng)目做多了,自然...
摘要:方法不僅適用于百度云,別的一些比較難以模擬登陸的網(wǎng)站都可以按照這種方式分析。本文要求讀者具有模擬登陸主要是抓包和閱讀代碼和密碼學(xué)的基本知識(shí)。和模擬登陸微博的分析流程一樣,我們首先要做的是以正常人的流程完整的登錄一遍百度網(wǎng)盤(pán)。 這是第二篇從簡(jiǎn)書(shū)搬運(yùn)過(guò)來(lái)的文章(大家別誤會(huì),是我原創(chuàng)的)。因?yàn)榍耙黄恼?,我看反響還挺好的,所以把這篇也搬運(yùn)過(guò)來(lái)了,其實(shí)目的還是為宣傳自己的分布式微博爬蟲(chóng)(該項(xiàng)目...
摘要:楚江數(shù)據(jù)是專業(yè)的互聯(lián)網(wǎng)數(shù)據(jù)技術(shù)服務(wù),現(xiàn)整理出零基礎(chǔ)如何學(xué)爬蟲(chóng)技術(shù)以供學(xué)習(xí),。本文來(lái)源知乎作者路人甲鏈接楚江數(shù)據(jù)提供網(wǎng)站數(shù)據(jù)采集和爬蟲(chóng)軟件定制開(kāi)發(fā)服務(wù),服務(wù)范圍涵蓋社交網(wǎng)絡(luò)電子商務(wù)分類信息學(xué)術(shù)研究等。 楚江數(shù)據(jù)是專業(yè)的互聯(lián)網(wǎng)數(shù)據(jù)技術(shù)服務(wù),現(xiàn)整理出零基礎(chǔ)如何學(xué)爬蟲(chóng)技術(shù)以供學(xué)習(xí),http://www.chujiangdata.com。 第一:Python爬蟲(chóng)學(xué)習(xí)系列教程(來(lái)源于某博主:htt...
摘要:學(xué)了大半年之后成功轉(zhuǎn)行做前端了。包含大量其他神經(jīng)網(wǎng)絡(luò)庫(kù)中的包裝器和抽象,其中最值得注意的是,其中也包含一些機(jī)器學(xué)習(xí)的實(shí)用模塊。它是輕量級(jí)可擴(kuò)展的神經(jīng)網(wǎng)絡(luò)工具包,同時(shí)擁有友好的界面,可供機(jī)器學(xué)習(xí)的訓(xùn)練和預(yù)測(cè)使用。 題記:大二的時(shí)候發(fā)現(xiàn)人生苦短,所以信了拍神,開(kāi)始學(xué)Python。學(xué)了大半年之后成功轉(zhuǎn)行做前端了。來(lái)寫(xiě)個(gè)教程幫助大家入門(mén)Python。 Python零基礎(chǔ)入門(mén) 零基礎(chǔ)入門(mén)就得從最...
閱讀 3547·2021-11-17 17:01
閱讀 3951·2021-11-08 13:12
閱讀 2508·2021-10-08 10:04
閱讀 735·2021-09-29 09:35
閱讀 1450·2021-09-26 10:12
閱讀 2116·2021-09-07 09:58
閱讀 1985·2019-08-30 15:55
閱讀 2165·2019-08-30 13:14