Node爬虫:从网页中抽取数据

借助 Node.js 生态系统中的第三方模块 cheerio ,可以很轻松地从 html 中抽取数据。cheerio 是一个 HTML 解析器, 其实现灵活、快速、精简,API 非常接近 jQuery 。下面的代码,以爬取新浪博客为使用场景,展示如何抽取博客标题、每篇博文的标题、正文、时间、分类、图片等数据。

const urlParse = require('url').parse
const path = require('path')
const cheerio = require('cheerio')
const isUrl = require('is-url')
const htmlDownloader = require('./htmlDownloader')

module.exports = async function extract(uid) {
  let data = {uid, urls: [], post: [], imgs: []}

  // 遍历博文目录,抽取博客标题,博文地址
  let i = 1, page = 1
  do {
    let list = await htmlDownloader(`http://blog.sina.com.cn/s/articlelist_${uid}_0_${i}.html`).catch(console.error)
    let $ = cheerio.load(list)
    $('.articleList a[title]').each((i, el) => {
      let href = $(el).attr('href')
      if (isUrl(href)) data.urls.push(href)
    })
    if (i === 1) {
      page = ($('span[style]').text().match(/\d+/) || [0])[0] // 总页数
      data.title = $('title').text().split('_')[1]  // 博客标题
      data.link = $('.blogtitle a').attr('href')    // 博客链接
    }
  } while (i++ <= page)

  // 遍历博文地址,抽取博文内容(标题、正文、时间、分类、图片、原文链接)
  for (let link of data.urls) {
    let post = await htmlDownloader(link).catch(console.error)
    let $ = cheerio.load(post, {decodeEntities: false})
    let title = $('.titName').text()       // 博文标题
    let date = $('.time.SG_txtc').text().replace(/(\(|\))/g, '')   // 博文发布时间
    let cate = $('.blog_class a').text()      // 博文分类
    let content = ''
    // 有2种博文页面,根据title判断
    if (title) {
      content = $('div.articalContent').html()
    } else {
      title = $('.h1_tit').text()
      content = $('div.BNE_cont').html()
    }
    // 去掉span、font、a等无用标签,抽取正文内容中的图片地址,并替换为本地图片地址
    content.replace(/<(p)[^>]*/gi, '<$1')
      .replace(/\n?<\/?(span|font)[^>]*>\n?/gi, '')
      .replace(/<a[^>]*><\/a>/gi, '')
      .replace(/<img[^>]*real_src="([^"]*)"([^>]*)>/gi, (m, url, b) => {
        url = url.replace(/&amp\d*/gi, '');
        let name = path.parse(urlParse(url).pathname).base
        if (!data.imgs.find(it => it.url === url)) {
          data.imgs.push({name, url})
        }
        return `<img src="../imgs/${name}"${b}>`
      })
      .replace(/<a[^>]*>(<img[^>]*>)<\/a>/gi, '$1')
      .trim()
    data.post.push({title, date, cate, link, content})
  }

  // 返回抽取的数据
  return data
}

上述代码使用了第三方模块 is-url ;使用正则表达式去除一些无用的标签,如span、font;还使用正则表达式抽取页面中的图片地址,并替换为本地地址,这可以方便后续生成 html 页面,或者 epub、mobi 等格式的电子书。

 

转载于:https://my.oschina.net/junyiz/blog/1616340

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值