Skip to content
nodejs爬虫斗鱼直播间数据
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
static
.gitignore
README.md
app.js
first.js
package.json

README.md

nodejs爬虫入门---斗鱼直播间数据

前提

如果需要,可以clone到本地

$ npm install --save
$ node app

打开http://localhost:3030/index.html 可直接查看爬虫数据

目标

爬取斗鱼正在直播的主播数据(房间号,在线人数,房间标题,主播名称,直播分类等等)

依赖构建

安装npm包express+superagent+cheerio

$ npm install express superagent cheerio --save
  • express:Node.js的Web应用程序框架
  • superagent:小型渐进式客户端HTTP请求库,和Node.js模块具有相同的API,具有许多高级HTTP客户端功能
  • cheerio:可以理解为一个Node.js版本的jquery,用来从网页中以 css selector取数据,使用方式和jquery基本相同

实现步骤

1、引入依赖并实例化express

const express = require('express');
const superagent = require('superagent');
const cheerio = require('cheerio');
const app = express();

2、定义目标url

const url = 'https://www.douyu.com/directory/all';
const rooturl = 'https://www.douyu.com';

rooturl是斗鱼首页,url是斗鱼全部直播间第一页,rooturl后面直播间地址数据要用到

3、发送请求 获取数据 分析数据 生成页面数据到前端

  • 用superagent发送get请求到斗鱼,回调函数接受到的数据给cheerio解析,这样就可以用jquery选择器进行操作
  • 使用cheerio.load()解析
  • 打开斗鱼,发现其直播列表均在id为live-list-contentbox的ul里,用jquery选择器获取所有li并遍历
  • 在li里寻找到我们需要的数据,最后push到data里
app.get('/', function (req, response) { // 声明get请求在指定的路径下调用相应的回调函数
   let data = [];//存放获取的数据
   superagent.get(url).end(function (err, res) {//发起get请求
       if (err) {
           console.log(err);
       } else {
           console.log('状态码:' + res.status);
           let $ = cheerio.load(res.text);//使用cheerio解析数据
           $('#live-list-contentbox li').each(function (i, ele) { //获取目标数据 并遍历存放到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);//目标数据发送给前端
   });
})

4、监听端口

app.listen(3000, function () { //监听3000端口
  console.log('server is listening port 3000....');
})

最后node这个项目,打开http://localhost:3000/ 得到我们需要的数据

  • 以上全部代码在first.js里.
    爬虫数据展示:

进阶爬虫

  • 思考:这只是斗鱼第一页主播的数据,如果是100页的数据,或者全部呢?

这时候就需要async,不可能同步发100个请求,容易被误以为恶意攻击
  • Async提供了直接,强大的函数来处理异步JavaScript,虽然最初设计用于Node.js,但它也可以直接在浏览器中使用
$ npm install async --save

分析页面

100个页面可以先获取100个相应的url,但是发现斗鱼切换到第二页的时候其url并没有改变,
通过chrome devtools发现在切换页面时的ajax请求。
发现ajax请求的url是https://www.douyu.com/gapi/rkc/directory/0_0/2 ,后面加的/2就是相应的页数(这里是第二页)

实现爬虫

1、和刚才上面一样

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、声明一个函数获取所有的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;
}

传进去的num是多少,返回的url就有多少

3、async异步发送请求

app.get('/data', function (req, res) {
    let urls = geturls(100); //获取100个url
    let datas = []; //存放目标数据
    async.mapLimit(urls,25,function (url, callback) { //异步发送请求
        fetchPage(url, callback);//分析数据并提取
    }, function (err, result) {
        console.log('分析完成!');
        res.send(datas);//发送数据给前端
    });
})

async.mapLimit(coll, limit, iteratee, callback)

  • coll是迭代的集合,就是数组存放需要发送请求的url
  • limit一次最大异步操作数
  • 一个异步函数,用于应用于每个项目 coll
  • callback可选,所有iteratee 函数完成或发生错误时调用的回调。 ps:最后一个函数里result参数的数据和datas数组数据是一样的,发送datas主要是方便后面页面提取

4、分析页面函数

function fetchPage(url, callback) {
        superagent.get(url).end(function (err, sres) {
            if (err) {
                console.log(err);
            } else {
                let item = JSON.parse(sres.text);//解析json数据
                let list = item.data.rl;
                list.forEach(function (ele) {//提取需要的数据
                    let obj = {
                        name: ele.nn,
                        id: ele.rid,
                        online: ele.ol,
                        title: ele.rn,
                        class: ele.c2name,
                    };
                    datas.push(obj);
                });
                callback(null, datas);//这个datas会发送给result
            }
        })
    }
})

因为ajax请求直接返回的是json数据就不需要上面的cheerio解析

5、设置静态文件目录

app.use(express.static('static'))

app.listen(3030, function () {
    console.log('server is listening port 3030....');
})

6、编写前端html,展示数据

  • 前端代码在index.html里,主要是获取数据遍历输出到表格,还有一个搜索功能(不建议搜索1W以上的数据,会很卡) 以上代码均在app.js里
You can’t perform that action at this time.