nodeJS(request+cheerio+pump)稳定爬取SSR网页数据

记录自己的爬虫经验

本次是爬取某SSR网站列表页及详情页数据,包括文本及图片,将数据存入MongoDB数据库,将图片下载至本地;

首先呢,用到的nodeJS模块有:

  1. request: 用于请求网址内容或请求图片内容
  2. cheerio: 通俗的讲,可以当做jQuery使用
  3. pump: 一种管道,操纵数据流,比原生的pipe好用,可操控性强,具体用法可去npm查询
  4. path: 读取操作文件路径
  5. fs: 操作文档读写等

第一步:引入需要用到的相关模块,建议用yarn安装以下模块

const request = require("request");

const cheerio = require("cheerio");

const path = require("path");

const fs = require("fs");

const pump = require("pump");

var Bagpipe = require(‘bagpipe‘);

第二步:连接Mongodb

//集合名称
const colName = ‘xiaorizi‘;
//1.引入模块中的客户端对象
const { MongoClient } = require(‘mongodb‘);
const { mongo: mongourl, database } = require(‘../config.json‘);

var client, db, collection
//2.利用MongoClient连接数据
(async function connect() {
    client = await MongoClient.connect(mongourl, { useNewUrlParser: true });
    //连接数据库,无则自动创建
    db = await client.db(database);
    //根据colName获取集合
    collection = await db.collection(colName);
})()

// @增 定义写入数据库函数
async function create(data) {
    //执行mongo增加数据语句
    let result;
    try {
        result = await collection[Array.isArray(data) ? ‘insertMany‘ : ‘insertOne‘](data);
    } catch (err) {
        result = err;
    }
}

第三步:配置需要用到的全局变量

//配置网址
let base = "7595"
//配置列表页数
let len = 2;
//配置店铺类型
let lu = "film";

//配置图片名称类型
let lujin = "./" + lu + "/" + lu + "_";
//配置请求基本网址
let baseurl = "http://m.xiaorizi.me/t" + base;

//生成列表页网址数组
let arr = [];
for (var j = 0; j < len; j++) {
    arr[j] = baseurl + "_p" + (j + 1) + "/";
}
console.log(arr);

//所有页店铺数量
let list_num = 0;

//所有详情页图片数量
let list_imgNum = 1;

第四步:开启进程

//开启10个进程爬取详情页图片
var bagpipe = new Bagpipe(10);
//开启4个进程爬取列表页图片
var bagpipe1 = new Bagpipe(4);
//记录爬取成功的详情页图片数量
var index = 1;

//定义下载图片函数
function downloadImage(src, dest, callback) {
  request.head(src, function (err, res, body) {
    // console.log(‘content-type:‘, res.headers[‘content-type‘]);
    // console.log(‘content-length:‘, res.headers[‘content-length‘]);
    if (src) {
      var source = request(src);
      pump(source, fs.createWriteStream(dest)).on(‘close‘, function () {
        callback(null, dest);
      });
    }
  })
}

第五步:遍历所有页面,爬取列表页及详情页

//遍历所有页
for (var g = 0; g < arr.length; g++) {

    //请求单页
    request(arr[g], async (error, response, body) => {
        //载入网站内容至body
        let $ = cheerio.load(body);
        // 利用jquery的核心方法获取html代码中的具体元素
        await $(‘.shops>li‘, ‘body‘).each(async (i, e) => {
            //标题
            let list_title = $(e).find("h3").text();
            //店铺
            let list_store = $(e).find(".tag").text();
            //地址
            let list_address = $(e).find("p").last().text();
            //图片src
            let list_imgSrc = $(e).find("a").first().find("img").attr("data-original");
            if (list_imgSrc) {
                //获取图片后缀名
                let back1 = path.basename(list_imgSrc).match(/[\.].+/);
                //将图片改名
                let list_imgName = lujin + list_imgNum++ + back1;
                //图片名称
                let list_Img = path.basename(list_imgName)
                //爬取列表页图片
                await bagpipe1.push(downloadImage, list_imgSrc, list_imgName, async (err, data) => {
                    //爬取详情页面
                    let detailSrc = "http://m.xiaorizi.me" + $(e).find("a").first().attr("href");
                    await request(detailSrc, async (err, res, bodys) => {
                        let $2 = cheerio.load(bodys);

                        //如果详情页存在
                        if ($2(".title_h")) {
                            list_num++;
                            //标题
                            let detail_title = [];
                            detail_title[0] = $2(".title_h").text();
                            detail_title[1] = $2(".title_p").text();
                            console.log("第" + list_num + "个店铺:", list_store)

                            //店铺详情
                            let detail_shop = [];
                            $2(".shop_detail li").each((i) => {
                                detail_shop[i] = $2($2(".shop_detail li")[i]).text();
                            })

                            //主要内容
                            let detail_cont = [];

                            //详情页图片数量
                            let detail_imgNum = 0;

                            //详情页文本及图片
                            $2(".content").children().each((i, e) => {
                                //如果到达底部结束标签p1则停止爬取
                                if ($2(e).prop("className") == "p1") {
                                    return;
                                }

                                //单个文本对象或图片对象
                                let obj = {};
                                obj.tagName = $2(e).prop("tagName");
                                if (obj.tagName == "P") {
                                    obj.value = $2(e).text();
                                    //如果P标签有内容再推入detail_cont数组
                                    if (obj.value != "") {
                                        detail_cont.push(obj);
                                    }
                                } else if (obj.tagName == "IMG") {
                                    //获取图片地址
                                    let detail_imgSrc = $2(e).attr("src");
                                    //匹配图片后缀名
                                    let back2 = path.basename(detail_imgSrc).match(/[\.].+/);
                                    //定义图片路径及名称
                                    let detail_imgName = lujin + "d_" + list_num + "_" + ++detail_imgNum + back2;
                                    obj.value = path.basename(detail_imgName);
                                    detail_cont.push(obj);

                                    //爬取详情页图片
                                    bagpipe.push(downloadImage, detail_imgSrc, detail_imgName, (err, data) => {
                                        console.log("[" + index++ + "]:" + data);
                                    })
                                }
                            })
                            create({
                                city: list_store.split(" ")[0],
                                type: list_store.split(" ")[1],
                                list_Img,
                                list_title,
                                list_store,
                                list_address,
                                detail_title,
                                detail_shop,
                                detail_cont
                            })
                        } else {
                            console.log("详情页不存在:" + list_store)
                        }
                    })
                })
            }
        })
    })
}

备注:config.json配置如下

{
    "PORT": 19011,
    "mongo": "mongodb://localhost:27017",
    "database": "runoob"
}

原文地址:https://www.cnblogs.com/dukeshao/p/10891675.html

时间: 2024-08-28 20:39:25

nodeJS(request+cheerio+pump)稳定爬取SSR网页数据的相关文章

定向爬取指定网页数据,并且过滤

需要爬取http://toutiao.com/i6192092485658378754/ 数据 问题1: 获得 页面的所有数据,并且过滤掉不需要的部分,或者指定需要的

利用selenium并使用gevent爬取动态网页数据

首先要下载相应的库 gevent协程库:pip install gevent selenium模拟浏览器访问库:pip install selenium selenium库相应驱动配置  https://www.cnblogs.com/Niuxingyu/p/10490882.html #导包 import gevent #猴子补丁 from gevent import monkey monkey.patch_all() import requests import os import re f

Scrapy 通过登录的方式爬取豆瓣影评数据

Scrapy 通过登录的方式爬取豆瓣影评数据 爬虫 Scrapy 豆瓣 Fly 由于需要爬取影评数据在来做分析,就选择了豆瓣影评来抓取数据,工具使用的是Scrapy工具来实现.scrapy工具使用起来比较简单,主要分为以下几步: 1.创建一个项目 ==scrapy startproject Douban 得到一个项目目录如下: ├── Douban │   ├── init.py │   ├── items.py │   ├── pipelines.py │   ├── settings.py

Python 爬取简单网页

1 import urllib.request 2 url = "http://www.baidu.com/s?wd=" #get网址格式:"https://www.baidu.com/s?wd=关键字" 3 key="周杰伦" 4 key_code=urllib.request.quote(key) # 汉字编码转化 5 url_all=url+key_code 6 req=urllib.request.Request(url_all) 7 d

爬虫毕设(三):爬取动态网页

动态网页分析 按照上一篇的分析,直接使用XPath找到该标签,然后通过parse提取出数据,在写入到item中就完事了.但是,当信心满满的写完代码后却发现,控制台输入了一个简简单单的[]. 小问号你是否有很多朋友. 一顿操作猛如虎,一看输出数据无.那么这到底是怎么回事呢?我们从头开始分析. 打开NetWork,找到tv/,点开Preview,结果发现只有一个框架,内容却是空白的. 这是由于网页执行js代码,通过Ajax请求数据来重新渲染页面的.所以我们需要找到有数据的那一个请求,然后再对该请求的

c#爬取Silverlight网页 2

此前的一篇文章:C#爬取Silverlight网页,描述了如何爬取加密的Silverlight网页,并以北京空气质量官网的破解进行了说明. 按此办法,我想继续破解由中山大学先进技术研究院开发的一系列的Silverlight网站,譬如福建省空气质量实时发布系统,却一无所获.关键在于找到密钥和盐值非常难.有时候reflector并不能工作. 其实我犯了一个错误,被此前的破解思路给羁绊了.下面我们以福建省空气质量实时发布系统为例,讲述如何破解此类的网站. 同北京空气质量站点一样,当用谷歌浏览器F12调

python爬取某个网页的图片-如百度贴吧

python爬取某个网页的图片-如百度贴吧 作者:vpoet 日期:大约在冬季 注:随意copy,不用告诉我 #coding:utf-8 import urllib import urllib2 import re if __name__ =="__main__": rex=r'src="(http://imgsrc.baidu.com/forum/w%3D580.*?\.jpg)"'; Response=urllib2.urlopen("http://t

使用htmlparse爬虫技术爬取电影网页的全部下载链接

昨天,我们利用webcollector爬虫技术爬取了网易云音乐17万多首歌曲,而且还包括付费的在内,如果时间允许的话,可以获取更多的音乐下来,当然,也有小伙伴留言说这样会降低国人的知识产权保护意识,诚然,我们的重点在于如何灵活运用我们已学的技术,这就需要我们不断的练习,不停的思索和深入发掘,在了解了精髓和意义之后运用到实践中才是技术的最高境界. 今天呢,本着昨天的兴趣,想来爬一爬电影资源,中途为了找一个好用趁手的工具,也是费了不少心思,早上半天基本上都在学习和找资料的过程中度过,下午开始才进入状

Python爬取京东商品数据

对京东某一商品信息页面的HTML代码进行分析,可以发现它的图书产品信息页面都含有这样一段代码(不同类的商品页面有些不同): window.pageConfig={compatible:true,searchType: 1,product:{"skuid":"11408255","name":"\u4f17\u795e\u7684\u536b\u661f\uff1a\u4e2d\u56fd\u7981\u533a","