nodejs+webdriver 爬虫

所需工具

  1. webdirver chrome 下载地址(需科学上网)
  2. nodejs

思路

  1. 抓取目标网页内容
  2. 匹配数据 dom 节点
  3. 获取数据并保存

准备

  • 安装所需依赖包
  1. selenium-webdriver 浏览器驱动包
  2. axios http 请求包
npm i selenium-webdriver axios
  • 引入所需依赖包
const { By, Builder } = require('selenium-webdriver')
const chrome = require('selenium-webdriver/chrome')
const fs = require('fs')
const { promisify } = require('util') // 将原始回调Promise化
const md5 = require('md5') // 给文件名起名字用 也可自己随意
const axios = require('axios')

注意:这里用的是 es8 async/await 语法

// 外层函数
async function run () {
  /*
    .................
    */
}

初始化 chromedirver

const driver = new Builder()
  .forBrowser('chrome')
  // .setChromeOptions(new chrome.Options().addArguments(['--headless'])) // 这里是chromedriver设置的参数
  .build()

示例网站(仅为学习用,如侵权必删)

https://www.mzitu.com/

抓取目标网页内容

await driver.get('https://www.mzitu.com')

匹配数据 dom 节点获取数据 这里用 xpath 选择器

onst els = await driver.findElements(By.xpath('//ul[@id="pins"]/li'))
  const data = []
  /* const h= await el.getAttribute('outerHTML') // 调试 查看选中的元素内容
      console.log(h);*/
  for (let el of els) {
    const title = await el
      .findElement(By.xpath('.//img'))
      .then(el => el.getAttribute('alt'))
      .catch(e => false)
    if (!title) continue
    const href = await el
      .findElement(By.xpath('.//a'))
      .then(el => el.getAttribute('href'))
      .catch(e => false)
    if (!href) continue
    data.push({ title, href })
  }

获取详情数据,保存

// 创建根目录
const rootDir = __dirname + '/imgs'
const exists = await promisify(fs.exists)(rootDir)
if (!exists) {
  await promisify(fs.mkdir)(rootDir)
}

for (let i of data) {
  // 根据title名创建子目录
  const itemDir = rootDir + '/' + i.title
  const exists = await promisify(fs.exists)(itemDir)
  if (!exists) {
    await promisify(fs.mkdir)(itemDir)
  }
  // 爬取内容页
  await driver.get(i.href)
  // 获取内容页最大页数
  let maxPage = await driver
    .findElement(By.xpath('//div[@class="pagenavi"]/a[last()-1]'))
    .then(e => e.getText())
  maxPage = parseInt(maxPage)
  // 命名文件
  const baseName = md5(i.title)
  for (let page = 1; page <= maxPage; page++) {
    try {
      const filePath = itemDir + '/' + baseName + '_' + page + '.jpg'
      // 判断该条是否已经抓取保存
      const exists = await promisify(fs.exists)(filePath)
      if (exists) {
        console.log('exists: ' + filePath)
        continue
      }
      // 抓取图片
      await driver.get(i.href + '/' + page)
      const src = await driver
        .findElement(By.xpath('//div[@class="main-image"]//img'))
        .then(e => e.getAttribute('src'))
      const { data } = await axios.get(src, {
        responseType: 'stream',
        headers: {
          referer: 'https://www.mzitu.com/',
          'user-agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36'
        }
      })
      // 保存图片
      await data.pipe(fs.createWriteStream(filePath))
      console.log(filePath)
      await promisify(setTimeout)(500)
    } catch (e) {
      console.log(e, '**************continue')
      await promisify(setTimeout)(5000)
      page--
    }
    // process.exit(filePath,src)
  }
}

关闭驱动

driver.close()
点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注