node爬虫爬取豆瓣电影数据

简介

SuperAgent是一个轻量级、灵活的、易读的、低学习曲线的客户端请求代理模块,使用在NodeJS环境中。
cheerio是jquery核心功能的一个快速灵活而又简洁的实现,主要是为了用在服务器端需要对DOM进行操作的地方
Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome 默认以 headless 模式运行,但是可以通过修改配置文件运行“有头”模式。

文档

superagent文档
puppeteer文档

安装

npm install superagent cheerio puppeteer

superagent 只能获取服务端渲染的数据,如果数据由js异步加载则无法获取,

代码

由于豆瓣的电影数据部分是有ajax异步加载的,不能使用直接superagent来爬取,要用puppeteer配合,先使用superagent获取由链接(速度快),再通过puppeteer根据链接爬取电影详情数据

完整代码

const superagent = require('superagent');
const cheerio = require('cheerio');
const puppeteer = require('puppeteer');
const fs = require('fs');

let movieURL = [] //存放链接
var movieIdex = 0  //计数
let index=3 //点击次数

getFile('img')
puppData()

// 先使用puppeteer爬取链接
async function puppData() {
    const browser = await puppeteer.launch({ headless: false, ignoreDefaultArgs: ["--enable-automation"] });
    const page = await browser.newPage();
    await page.goto(`https://movie.douban.com/tag/#/?sort=U&range=0,10&tags=&start=0`);
    await page.setDefaultNavigationTimeout(600000);
    await page.waitFor('.more');
    let timer = setInterval(async function () {//3秒点一次加载更多
        await page.click('.more');
        movieIdex++
        if (movieIdex >= index) {
            clearInterval(timer)
            let a = await page.$$eval('.list-wp>.item', e => {
                let arr = []
                for (var i = 0; i < e.length; i++) {
                    arr.push(e[i].href)
                }
                return arr
            })
            await browser.close(); //爬取链接完成,关闭无头浏览器
            movieURL.push(...a)
            fs.writeFile('b.json', JSON.stringify(movieURL), { flag: 'a', encoding: 'utf-8', mode: '0666' }, function (err) { //保存在b.json
                if (err) throw err;
                fs.readFile('b.json', 'utf8', (err, doc) => {//由于怕中途出错误,所以先把链接保存到b.json,再读取b.json
                    if (err) throw err;
                    let bItem = JSON.parse(doc)
                    bItem.map((item) => {
                        getVideo(item)
                    })
                })
            })
        }
    }, 3000)
}

// 用superagent爬取电影数据
async function getVideo(url) {
    let html = await superagent.get(url);
    let $ = cheerio.load(html.text);
    let protagonist = ''
    $('#info>span').eq('2').find('a').text(function (index, item) {
        return protagonist += item + '|'
    })
   var info = {
        url: getImg($('#mainpic img').attr('src')),  //图片
        name: $('h1').find('span').text(),  //片名
        year: $('h1 .year').text(),  //时间
        grade: $('.rating_num').text(), //评分
        rating_people: $('.rating_people span').text(), //影评数
        director: $('#info>span').eq('0').find('a').text(), //导演
        scriptwriter: $('#info>span').eq('1').find('a').text(), //编剧
        protagonist, //主演
        type: $('#info>span').eq('5').text() + '|' + $('#info>span').eq('6').text(), //类型
        releaseDate: $('#info>span').eq('-5').text(),//上映日期
        min: $('#info>span').eq('-3').text(),//片长
        brief:$('#link-report span').text()//简介
    }
    fs.writeFile('a.json', JSON.stringify(info)+',', { flag: 'a', encoding: 'utf-8', mode: '0666' }, function (err) {
        if (err) throw err;
    })
}

//爬取图片
function getImg(imgUrl) {
    let name = randomString(32) + '.jpg'
    superagent
        .get(imgUrl)
        .end(function (err, sres) {
            if (err) throw err;
            fs.writeFile("./img/" + name, sres.body, "binary", function (err) {
                if (err) throw err;
            })
        })
    return name
}


//创建img文件
function getFile(file) {
    if (!fs.existsSync(file)) {
        fs.mkdirSync(file);
    }
}

//对图片重命名
function randomString(len) {
    len = len || 32;
    var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
    var maxPos = $chars.length;
    var pwd = '';
    for (let i = 0; i < len; i++) {
        pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return pwd;
}

你可能感兴趣的:(node)