millzhang/MarkdownBlog

爬虫1.0

Opened this issue · 0 comments

前言

上次我们使用nightmare这款自动化测试工具进行了百度图片关键词查询结果的爬虫,效率略低.
现在我们尝试其他的方式,更高效的进行爬虫操作.这里使用的npm包主要有:

  • axios
  • cheerio //本次没有用到
  • mysql //我们需要把数据记录下来
  • log4js //提供一个清晰的日志跟踪

环境准备

  • 安装MySQL,搭建本地数据库
  • 安装上述模块
  • 配置log4js,这里不详述具体的配置方法
  • 准备数据库操作的模块,这里也不详述

开始

这次我们爬取的目的,依然是百度图库,关键字查找.

调研

首先,确认了目前百度图片关键字查找后,图片采用滚动懒加载的方式,所以切换到network,

简单分析下:

  • 懒加载使用get方式
  • 请求头连接是https://image.baidu.com/search/acjson
  • request参数我们去除空无效非关键的字段,应当如下:
{
 	tn: 'resultjson_com',//这个参数不能少
    ipn: 'rj',//这个参数也不能少
    queryWord: '',//查询关键词
    word:'',//查询关键词
    pn: 30,//这个是当前页的数量
    rn: 30//这个是每页的大小
}
  • 然后response的结构大概是这样的:

  • data里是个数组,我们关心的是data内,子项的数据结构:

里面有很多数据,我们目前只关心图片url和图片来源的网站,分别是thumbURL,fromURLHost

axios发送请求

let pageNum = config.page.num,
    pageSize = config.page.size;
let imageList = new Set(),
    hostList = new Set();
const getImageByPage = async(page) => {
    return axios.get('https://image.baidu.com/search/acjson', {
        params: {
            tn: 'resultjson_com',
            ipn: 'rj',
            queryWord: config.keywords,
            word: config.keywords,
            pn: page,
            rn: pageSize
        }
    }).then(response => {
        logger.info(`请求成功,开始解析数据,当前是第${page}页......`);
        let resData = response.data,
            lazyData = resData.data;
        logger.debug(`请求成功,数据长度为${undefined == lazyData ? 0 : lazyData.length}`);
        if (undefined == lazyData) true;
        let result = [];
        lazyData.forEach(item => {
            if (undefined != item.thumbURL) {
                imageList.add(item.thumbURL);
                hostList.add(item.fromURLHost);
                result.push(item.thumbURL);
                //执行数据库插入操作
                db.insert(`insert into baidu_image(host,url) values("${item.fromURLHost}","${item.thumbURL}")`);
            }
        });
        return true;
    }).catch(e => {
        logger.error(e.message);
        return false;
    });
}

控制请求数量

const run = async() => {
    //发送一个请求
    for (let i = 0; i < config.page.times; i++) {
        logger.debug(`开始第${i+1}次请求`)
        if (await getImageByPage(pageNum)) {
            pageNum += pageSize;
        } else {
            logger.debug('没有了,终止循环');
            break;
        }
    }
    logger.debug(`一共获取到${imageList.size}张图片`);
}

结果