nodejs之爬虫

爬虫

使用场景:目标服务器无接口,采用SSR方式渲染的网站

  1. 分析html结构,找出需要爬取的区域特点
  2. 使用特定工具
    • request 用于获取目标html结构
    • cheerio 用户过滤和获取数据(一个类似与jquery的工具,可以使用jq选择器)
  3. 把得到的数据写入数据库
  4. 下载图片到本地

stream数据流

  • fs.readFile() 写入文件
  • fs.createReadStream() 读取文件流
  • fs.createWriteStream() 写入文件流

在这里插入图片描述

/**
 * 
 * 1、请求的网站数据
 * 2、将数据保存本地文件
 * 
 */

//  通过一个http请求,获取一个网站的信息

const http = require('http')
const fs=require('fs')
let url = 'http://www.baidu.com/'

http.get(url, (res) => {
  // 数据分段,只要接收数据就会触发data 事件 chunk 每次接收的数据片段
  // 用于拼接 chunk 数据片段 就是下面的字符串拼接
  let rawData = ''
  res.on('data', (chunk) => {
    // console.log('数据传输')
    // console.log(chunk) // chunk 指每次传输过来的数据有哪些
    // console.log(chunk.toString('utf8'))
    rawData += chunk.toString('utf8')
  })
  res.on('end', () => {
    // 将请求的数据保存到本地
    fs.writeFileSync('./baidu.html',rawData)
    console.log('数据库传输完毕')
  })
}).on("error", (err) => {
  console.log('请求错误')
})

下面说一个模块 cheerio :用户过滤和获取数据(一个类似与jquery的工具,可以使用jq选择器)

const cheerio = require('cheerio')
let $ = cheerio.load('<div><p>hello world</p><img src="http://baidu1.com"><img src="http://baidu2.com"><img src="http://baidu3.com"></div>')

// 将一组HTML格式的字符串转化为类DOM元素,之后可以通过jq的语法选中其中的元素
console.log($('img').attr('src'))
console.log($('p').html())

// 遍历
$('img').each((index, el) => {
  console.log($(el).attr('src'))
})

在这里插入图片描述

/**
 * 
 * 1、请求的网站数据
 * 2、将数据保存本地文件
 * 
 */

//  通过一个http请求,获取一个网站的信息

const http = require('https')
const fs = require('fs')
const cheerio = require('cheerio')

let url = 'https://www.csdn.net'
// http.get 可以是 json 看官网文档
// let json = 'http://nodejs.org/dist/index.json'

http.get(url, (res) => {
  // 安全判断
  const {
    statusCode
  } = res; //状态码
  const contentType = res.headers['content-type']; //文件类型
  // console.log(statusCode, contentType)

  let error = null;
  // 任何 2xx 状态码都表示成功的响应,但是这里只检查 200。
  if (statusCode !== 200) {
    error = new Error('请求失败\n' + `状态码: ${statusCode}`);
  } else if (!/^text\/html/.test(contentType)) {
    error = new Error('无效的 content-type.\n' + `期望的是 text/html 但接收到的是 ${contentType}`);
  }
  // error 为真 两个判断出错
  if (error) {
    console.error(error.message);
    // 响应的数据来释放内存。
    res.resume();
    return;
  }

  // 数据处理
  // 数据分段,只要接收数据就会触发data 事件 chunk 每次接收的数据片段
  // 用于拼接 chunk 数据片段 就是下面的字符串拼接
  let rawData = ''
  res.on('data', (chunk) => {
    // console.log('数据传输')
    // console.log(chunk) // chunk 指每次传输过来的数据有哪些
    // console.log(chunk.toString('utf8'))
    rawData += chunk.toString('utf8')
  })
  res.on('end', () => {
    // 将请求的数据保存到本地
    // fs.writeFileSync('./baidu.html', rawData)
    console.log('数据库传输完毕')
    // 通过 cheerio 分析
    let $ = cheerio.load(rawData) //将请求的网页进行转化
    $('img').each((index, el) => {
      console.log($(el).attr('src')) //爬取网页中img的src
    })
  })
}).on("error", (err) => {
  console.log('请求错误')
})

在这里插入图片描述

下面用到第三方 request 和 cheerio模块

/**
 * 目标网址:http://store.lining.com/shop/goodsCate-sale,desc,1,15s15_122,15_122_m,15_122_ls15_122_10,15_122_10_m,15_122_10_l-0-0-15_122_10,15_122_10_m,15_122_10_l-0s0-0-0-min,max-0.html
 
 * 工具
    * request
    * cheerio
 */
const fs = require('fs');
const path = require('path');
const request = require('request');
const cheerio = require('cheerio');

// 1.获取目标html结构
const url = 'http://store.lining.com/shop/goodsCate-sale,desc,1,15s15_122,15_122_m,15_122_ls15_122_10,15_122_10_m,15_122_10_l-0-0-15_122_10,15_122_10_m,15_122_10_l-0s0-0-0-min,max-0.html';
request(url, (err, res, body) => {
  let $ = cheerio.load(body);
  const goodslist = []
  $('.cate_search_content').find('.selItem').each((idx, ele) => {
    const $ele = $(ele);
    const name = $ele.find('.hgoodsName').text();
    let price = $ele.find('.price').text()
    price = price.match(/[\d\.]+/)[0]
    const imgurl = $ele.find('.selMainPic img').attr('orginalsrc')


    // 2. 爬取图片到本地
    // request请求图片地址,返回一个数据流
    const filename = path.basename(imgurl);
    const fileStream = fs.createWriteStream('./img/' + filename);
    request(imgurl).pipe(fileStream);

    const goods = {
      name,
      price,
      imgurl: 'img/' + filename
    }
    goodslist.push(goods);
    
  });
  console.log(goodslist);
})

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值