摘要:前提本項(xiàng)目地址如果需要,可以到本地打開(kāi)可直接查看爬蟲(chóng)數(shù)據(jù)目標(biāo)爬取斗魚(yú)正在直播的主播數(shù)據(jù)房間號(hào),在線(xiàn)人數(shù),房間標(biāo)題,主播名稱(chēng),直播分類(lèi)等等依賴(lài)構(gòu)建安裝包的應(yīng)用程序框架小型漸進(jìn)式客戶(hù)端請(qǐng)求庫(kù),和模塊具有相同的,具有許多高級(jí)客戶(hù)端功能可以
前提
本項(xiàng)目github地址:https://github.com/janyin/dou...
如果需要,可以clone到本地
$ npm install --save
$ node app
打開(kāi)http://localhost:3030/index.html 可直接查看爬蟲(chóng)數(shù)據(jù)
目標(biāo)爬取斗魚(yú)正在直播的主播數(shù)據(jù)(房間號(hào),在線(xiàn)人數(shù),房間標(biāo)題,主播名稱(chēng),直播分類(lèi)等等)
依賴(lài)構(gòu)建安裝npm包express+superagent+cheerio
$ npm install express superagent cheerio --save
express:Node.js的Web應(yīng)用程序框架
superagent:小型漸進(jìn)式客戶(hù)端HTTP請(qǐng)求庫(kù),和Node.js模塊具有相同的API,具有許多高級(jí)HTTP客戶(hù)端功能
cheerio:可以理解為一個(gè)Node.js版本的jquery,用來(lái)從網(wǎng)頁(yè)中以 css selector取數(shù)據(jù),使用方式和jquery基本相同
實(shí)現(xiàn)步驟 1、引入依賴(lài)并實(shí)例化expressconst express = require("express"); const superagent = require("superagent"); const cheerio = require("cheerio"); const app = express();2、定義目標(biāo)url
const url = "https://www.douyu.com/directory/all"; const rooturl = "https://www.douyu.com";
rooturl是斗魚(yú)首頁(yè),url是斗魚(yú)全部直播間第一頁(yè),rooturl后面直播間地址數(shù)據(jù)要用到
3、發(fā)送請(qǐng)求 獲取數(shù)據(jù) 分析數(shù)據(jù) 生成頁(yè)面數(shù)據(jù)到前端用superagent發(fā)送get請(qǐng)求到斗魚(yú),回調(diào)函數(shù)接受到的數(shù)據(jù)給cheerio解析,這樣就可以用jquery選擇器進(jìn)行操作
使用cheerio.load()解析
打開(kāi)斗魚(yú),發(fā)現(xiàn)其直播列表均在id為live-list-contentbox的ul里,用jquery選擇器獲取所有l(wèi)i并遍歷
在li里尋找到我們需要的數(shù)據(jù),最后push到data里
app.get("/", function (req, response) { // 聲明get請(qǐng)求在指定的路徑下調(diào)用相應(yīng)的回調(diào)函數(shù) let data = [];//存放獲取的數(shù)據(jù) superagent.get(url).end(function (err, res) {//發(fā)起get請(qǐng)求 if (err) { console.log(err); } else { console.log("狀態(tài)碼:" + res.status); let $ = cheerio.load(res.text);//使用cheerio解析數(shù)據(jù) $("#live-list-contentbox li").each(function (i, ele) { //獲取目標(biāo)數(shù)據(jù) 并遍歷存放到data中 let href = rooturl + $(ele).find("a.play-list-link").attr("href");//href是存放的直播間id,加rooturl生成直播間鏈接 let lives = { name: $(ele).find("span.dy-name").text(), num: $(ele).find("span.dy-num").text(), title: $(ele).find(".mes-tit>h3").text().trim(), links: href,//直播間鏈接 }; data.push(lives); }) } response.send(data);//目標(biāo)數(shù)據(jù)發(fā)送給前端
})
4、監(jiān)聽(tīng)端口app.listen(3030, function () { console.log("server is listening port 3030...."); })
最后node這個(gè)項(xiàng)目,打開(kāi)http://localhost:3000/ 得到我們需要的數(shù)據(jù)
以上全部代碼在first.js里. 爬蟲(chóng)數(shù)據(jù)部分結(jié)果:
進(jìn)階爬蟲(chóng)
思考:這只是斗魚(yú)第一頁(yè)主播的數(shù)據(jù),如果是100頁(yè)的數(shù)據(jù),或者全部呢?
這時(shí)候就需要async,不可能同步發(fā)100個(gè)請(qǐng)求,容易被誤以為惡意攻擊
Async提供了直接,強(qiáng)大的函數(shù)來(lái)處理異步JavaScript,雖然最初設(shè)計(jì)用于Node.js,但它也可以直接在瀏覽器中使用
$ npm install async --save分析頁(yè)面
100個(gè)頁(yè)面可以先獲取100個(gè)相應(yīng)的url,但是發(fā)現(xiàn)斗魚(yú)切換到第二頁(yè)的時(shí)候其url并沒(méi)有改變,
通過(guò)chrome devtools發(fā)現(xiàn)在切換頁(yè)面時(shí)的ajax請(qǐng)求。
發(fā)現(xiàn)ajax請(qǐng)求的url是https://www.douyu.com/gapi/rk... ,后面加的/2就是相應(yīng)的頁(yè)數(shù)(這里是第二頁(yè))
const express = require("express"); const superagent = require("superagent"); const async = require("async"); const app = express(); const rooturl = "https://www.douyu.com/gapi/rkc/directory/0_0";2、聲明一個(gè)函數(shù)獲取所有的url
function geturls(num) { let href = []; let urls = []; for (let i = 1; i <= num; i++) { href.push("/" + i); } href.forEach(function (ele) { urls.push(rooturl + ele); }) return urls; }
傳進(jìn)去的num是多少,返回的url就有多少
3、async異步發(fā)送請(qǐng)求app.get("/data", function (req, res) { let urls = geturls(100); //獲取100個(gè)url let datas = []; //存放目標(biāo)數(shù)據(jù) async.mapLimit(urls,25,function (url, callback) { //異步發(fā)送請(qǐng)求 fetchPage(url, callback);//分析數(shù)據(jù)并提取 }, function (err, result) { console.log("分析完成!"); res.send(datas);//發(fā)送數(shù)據(jù)給前端 }); })
async.mapLimit(coll, limit, iteratee, callback)
coll是迭代的集合,就是數(shù)組存放需要發(fā)送請(qǐng)求的url
limit一次最大異步操作數(shù)
一個(gè)異步函數(shù),用于應(yīng)用于每個(gè)項(xiàng)目 coll
callback可選,所有iteratee 函數(shù)完成或發(fā)生錯(cuò)誤時(shí)調(diào)用的回調(diào)。
ps:最后一個(gè)函數(shù)里result參數(shù)的數(shù)據(jù)和datas數(shù)組數(shù)據(jù)是一樣的,發(fā)送datas主要是方便后面頁(yè)面提取
4、分析頁(yè)面函數(shù)function fetchPage(url, callback) { superagent.get(url).end(function (err, sres) { if (err) { console.log(err); } else { let item = JSON.parse(sres.text);//解析json數(shù)據(jù) let list = item.data.rl; list.forEach(function (ele) {//提取需要的數(shù)據(jù) let obj = { name: ele.nn, id: ele.rid, online: ele.ol, title: ele.rn, class: ele.c2name, }; datas.push(obj); }); callback(null, datas);//這個(gè)datas會(huì)發(fā)送給result } }) } })
因?yàn)閍jax請(qǐng)求直接返回的是json數(shù)據(jù)就不需要上面的cheerio解析
5、設(shè)置靜態(tài)文件目錄app.use(express.static("public")) app.listen(3030, function () { console.log("server is listening port 3030...."); })6、編寫(xiě)前端html,展示數(shù)據(jù)
前端代碼在index.html里,主要是獲取數(shù)據(jù)遍歷輸出到表格,還有一個(gè)搜索功能(不建議搜索1W以上的數(shù)據(jù),會(huì)很卡)
以上代碼均在app.js里
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97018.html
摘要:有什么作用通過(guò)有效的爬蟲(chóng)手段批量采集數(shù)據(jù),可以降低人工成本,提高有效數(shù)據(jù)量,給予運(yùn)營(yíng)銷(xiāo)售的數(shù)據(jù)支撐,加快產(chǎn)品發(fā)展。因?yàn)樾畔⑹峭耆_(kāi)的,所以是合法的。 showImg(https://segmentfault.com/img/remote/1460000011359885?w=566&h=316); 什么是爬蟲(chóng)? 網(wǎng)絡(luò)爬蟲(chóng)也叫網(wǎng)絡(luò)蜘蛛,如果把互聯(lián)網(wǎng)比喻成一個(gè)蜘蛛網(wǎng),那么蜘蛛就是在...
摘要:站的彈幕服務(wù)器也有類(lèi)似的機(jī)制,隨便打開(kāi)一個(gè)未開(kāi)播的直播間,抓包將看到每隔左右會(huì)給服務(wù)端發(fā)送一個(gè)心跳包,協(xié)議頭第四部分的值從修改為即可。 原文:B 站直播間數(shù)據(jù)爬蟲(chóng), 歡迎轉(zhuǎn)載項(xiàng)目地址:bilibili-live-crawler 前言 起因 去年在 B 站發(fā)現(xiàn)一個(gè)后期超強(qiáng)的 UP 主:修仙不倒大小眼,專(zhuān)出 PDD 這樣知名主播的吃雞精彩集錦,漲粉超快。于是想怎么做這樣的 UP,遇到的第一...
摘要:很基礎(chǔ),不喜勿噴轉(zhuǎn)載注明出處爬蟲(chóng)實(shí)戰(zhàn)項(xiàng)目之鏈家效果圖思路爬蟲(chóng)究竟是怎么實(shí)現(xiàn)的通過(guò)訪問(wèn)要爬取的網(wǎng)站地址,獲得該頁(yè)面的文檔內(nèi)容,找到我們需要保存的數(shù)據(jù),進(jìn)一步查看數(shù)據(jù)所在的元素節(jié)點(diǎn),他們?cè)谀撤矫嬉欢ㄊ怯幸?guī)律的,遵循規(guī)律,操作,保存數(shù)據(jù)。 說(shuō)明 作為一個(gè)前端界的小學(xué)生,一直想著自己做一些項(xiàng)目向全棧努力。愁人的是沒(méi)有后臺(tái),搜羅之后且學(xué)會(huì)了nodejs和express寫(xiě)成本地的接口給前端頁(yè)面調(diào)用...
摘要:很基礎(chǔ),不喜勿噴轉(zhuǎn)載注明出處爬蟲(chóng)實(shí)戰(zhàn)項(xiàng)目之鏈家效果圖思路爬蟲(chóng)究竟是怎么實(shí)現(xiàn)的通過(guò)訪問(wèn)要爬取的網(wǎng)站地址,獲得該頁(yè)面的文檔內(nèi)容,找到我們需要保存的數(shù)據(jù),進(jìn)一步查看數(shù)據(jù)所在的元素節(jié)點(diǎn),他們?cè)谀撤矫嬉欢ㄊ怯幸?guī)律的,遵循規(guī)律,操作,保存數(shù)據(jù)。 說(shuō)明 作為一個(gè)前端界的小學(xué)生,一直想著自己做一些項(xiàng)目向全棧努力。愁人的是沒(méi)有后臺(tái),搜羅之后且學(xué)會(huì)了nodejs和express寫(xiě)成本地的接口給前端頁(yè)面調(diào)用...
摘要:不過(guò)因?yàn)楦鱾€(gè)平臺(tái)互相挖人的關(guān)系,導(dǎo)致關(guān)注的一些主播分散到了各個(gè)直播平臺(tái),來(lái)回切換有點(diǎn)麻煩,所以萌生了做一個(gè)視頻聚合站的想法。后續(xù)我們會(huì)對(duì)這三個(gè)部分的功能做逐一展開(kāi)說(shuō)明。正則處理要求比較高,但是幾乎能應(yīng)對(duì)所有的情況,屬于大殺器。 前言 作為一個(gè)爐石傳說(shuō)玩家,經(jīng)常有事沒(méi)事開(kāi)著直播網(wǎng)站看看大神們的精彩表演。不過(guò)因?yàn)楦鱾€(gè)平臺(tái)互相挖人的關(guān)系,導(dǎo)致關(guān)注的一些主播分散到了各個(gè)直播平臺(tái),來(lái)回切換有點(diǎn)麻...
閱讀 3096·2023-04-25 20:43
閱讀 1727·2021-09-30 09:54
閱讀 1600·2021-09-24 09:47
閱讀 2889·2021-09-06 15:02
閱讀 3522·2021-02-22 17:09
閱讀 1245·2019-08-30 15:53
閱讀 1448·2019-08-29 17:04
閱讀 1969·2019-08-28 18:22