【nodejs爬虫】使用async控制并发写一个小说爬虫

最近在做一个书城项目,数据用爬虫爬取,百度了一下找到这个网站,以择天记这本小说为例。

爬虫用到了几个模块,cheerio,superagent,async。

superagent是一个http请求模块,详情可参考链接

cheerio是一个有着jQuery类似语法的文档解析模块,你可以简单理解为nodejs中的jQuery。

async是一个异步流程控制模块,在这里我们主要用到async的mapLimit(coll, limit, iteratee, callback)

async.mapLimit(urls, 10, function (url, callback) {
        fetchUrl(url, callback, id)
      }, function (err, results) {
        //TODO
      })

第一个参数coll是一个数组,保存了小说的章节url,第二个参数limit是控制并发数,第三个参数iteratee接受一个回调函数,该回调函数的第一个参数就是单独某一章的url,第二个参数也是一个回调函数,这个回调函数执行后会把结果(在这里就是每一章的内容)保存到第四个参数callback的results中,results是一个数组,保存了所有章节的内容。

我们在fetchUrl获取章节数据。

首先我们要根据小说的主页url获取所有章节的url保存到数组urls中:

superagent.get(url)
    .charset(‘gbk‘)  //该网站编码为gbk,用到了superagent-charset
    .end(function (err, res) {
      var $ = cheerio.load(res.text); //res.text为获取的网页内容,通过cheerio的load方法处理后,之后就是jQuery的语法了
      let urls = []
      total = $(‘#list dd‘).length
      console.log(`共${$(‘#list dd‘).length}章`)
      $(‘#list dd‘).each(function (i, v) {
        if (i < chapters) {
          urls.push(‘http://www.zwdu.com‘ + $(v).find(‘a‘).attr(‘href‘))
        }
      })

fetchUrl函数

function fetchUrl(url, callback, id) {
  superagent.get(url)
    .charset(‘gbk‘)
    .end(function (err, res) {
      let $ = cheerio.load(res.text)
      //obj为构建的包含章节信息的对象
      callback(null, obj)  //将obj传递给第四个参数中的results
    })
}

完整代码:

/**
 * Created by tgxh on 2017/7/4.
 */
const cheerio = require(‘cheerio‘)
const express = require(‘express‘)
const app = express()
const superagent = require(‘superagent‘)
require(‘superagent-charset‘)(superagent)
const async = require(‘async‘);

let total = 0 //总章节数
let id = 0 //计数器
const chapters = 10 //爬取多少章
const url = ‘http://www.zwdu.com/book/8634/‘

//去除前后空格和&nbsp;转义字符
function trim(str) {
  return str.replace(/(^\s*)|(\s*$)/g, ‘‘).replace(/&nbsp;/g, ‘‘)
}

//将Unicode转汉字
function reconvert(str) {
  str = str.replace(/(&#x)(\w{1,4});/gi, function ($0) {
    return String.fromCharCode(parseInt(escape($0).replace(/(%26%23x)(\w{1,4})(%3B)/g, "$2"), 16));
  });
  return str
}

function fetchUrl(url, callback, id) {
  superagent.get(url)
    .charset(‘gbk‘)
    .end(function (err, res) {
      let $ = cheerio.load(res.text)
      const arr = []
      const content = reconvert($("#content").html())
      //分析结构后分割html
      const contentArr = content.split(‘<br><br>‘)
      contentArr.forEach(elem => {
        const data = trim(elem.toString())
        arr.push(data)
      })
      const obj = {
        id: id,
        err: 0,
        bookName: $(‘.footer_cont a‘).text(),
        title: $(‘.bookname h1‘).text(),
        content: arr.join(‘-‘)  //由于需要保存至mysql中,不支持直接保存数组,所以将数组拼接成字符串,取出时再分割字符串即可
      }
      callback(null, obj)
    })
}

app.get(‘/‘, function (req, response, next) {
  superagent.get(url)
    .charset(‘gbk‘)
    .end(function (err, res) {
      var $ = cheerio.load(res.text);
      let urls = []
      total = $(‘#list dd‘).length
      console.log(`共${$(‘#list dd‘).length}章`)
      $(‘#list dd‘).each(function (i, v) {
        if (i < chapters) {
          urls.push(‘http://www.zwdu.com‘ + $(v).find(‘a‘).attr(‘href‘))
        }
      })

      async.mapLimit(urls, 10, function (url, callback) {
        id++
        fetchUrl(url, callback, id) //需要对章节编号,所以通过变量id来计数
      }, function (err, results) {
        response.send(results)
      })
    })
})

app.listen(3378, function () {
  console.log(‘server listening on 3378‘)
})

结果如下:

时间: 2024-10-10 07:32:12

【nodejs爬虫】使用async控制并发写一个小说爬虫的相关文章

爬虫入门 手写一个Java爬虫

本文内容 涞源于  罗刚 老师的 书籍 << 自己动手写网络爬虫一书 >> ; 本文将介绍 1: 网络爬虫的是做什么的?  2: 手动写一个简单的网络爬虫; 1: 网络爬虫是做什么的?  他的主要工作就是 跟据指定的url地址 去发送请求,获得响应, 然后解析响应 , 一方面从响应中查找出想要查找的数据,另一方面从响应中解析出新的URL路径, 然后继续访问,继续解析;继续查找需要的数据和继续解析出新的URL路径  . 这就是网络爬虫主要干的工作.  下面是流程图: 通过上面的流程图

如何用SHELL写好网络爬虫

上周,老大压下来任务,让写一个网络爬虫,负责爬某一个行业网站的数据信息.由于本人只会 shell 编程语言,其它编程语言从未涉猎,因此就只能硬着头皮用 shell 去写了. 转眼之前已经过去一周了,一切从无到有,经历的坎坷无数,这里我就不一一吐槽. 这里呢,我就简单和大家分享下,我个人对,如何用 shell 去写好网络爬虫的几点拙见,希望有想法的朋友联系我一起交流交流想法,没有想法的就看看有精华就吸收走,有糟粕的果断弃之. 1.你肯定要简单了解下网络爬虫是什么!这个定义在谷歌一搜一大堆,这里我就

一个咸鱼的python爬虫之路(五):scrapy 爬虫框架

介绍一下scrapy 爬虫框架 安装方法 pip install scrapy 就可以实现安装了.我自己用anaconda 命令为conda install scrapy. 1 Engine从Spider处获得爬取请求(Request)2Engine将爬取请求转发给Scheduler,用于调度 3 Engine从Scheduler处获得下一个要爬取的请求4 Engine将爬取请求通过中间件发送给Downloader5 爬取网页后,Downloader形成响应(Response)通过中间件发给En

nodejs写的一个网页爬虫例子(坏链率)

因为工作需要,用nodejs写了个简单的爬虫例子,之前也没用过nodejs,连搭环境加写大概用了5天左右,so...要多简陋有多简陋,放这里给以后的自己看~~ 整体需求是:给一个有效的URL地址,返回该网页上所有无效链接的百分比(坏链率) 第一个文件:计算环链率 urlSpider.js 1 /*================================================ 2 @author MissUU 3 链接抓取思路: 4 5 1. 获取页面内容 6 2. 正则取得所有

用NodeJs做一个小爬虫

作者:北京起步科技前端研究员,专注分享HTML5 App快速开发工具 WeX5 的黑魔法以及相应的前端技术. 前言 利用爬虫可以做很多事情,单身汉子们可以用爬虫来收集各种妹子情报,撩妹族们可以用爬虫收集妹子想要的小东西,赚大钱的人可以用来分析微博言论与股票涨跌的关系诸如此类的,简直要上天了. 你们感受一下 点我点我: 蠢蠢欲动 抛开机器学习这种貌似很高大上的数据处理技术,单纯的做一个爬虫获取数据还是非常简单的.对于前段er们来说,生在有nodejs的年代真是不要太幸福了,下面就用nodejs来做

Hello Python!用python写一个抓取CSDN博客文章的简单爬虫

网络上一提到python,总会有一些不知道是黑还是粉的人大喊着:python是世界上最好的语言.最近利用业余时间体验了下python语言,并写了个爬虫爬取我csdn上关注的几个大神的博客,然后利用leancloud一站式后端云服务器存储数据,再写了一个android app展示数据,也算小试了一下这门语言,给我的感觉就是,像python这类弱类型的动态语言相比于java来说,开发者不需要分太多心去考虑编程问题,能够把精力集中于业务上,思考逻辑的实现.下面分享一下我此次写爬虫的一下小经验,抛砖引玉

用Python写一个最简单的网络爬虫

什么是网络爬虫?这是百度百科的解释: 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁,自动索引,模拟程序或者蠕虫. 爬虫可以做什么?爬虫可以帮助我们在茫茫互联网中爬取我们需要的特定数据,这个特定数据可以是任何想获得的数据. 爬虫是一个让人热血的话题,因为当你在写爬虫的时候,你会感觉到自己是在做一件很NB的事,而每当写出一个爬虫,就会在此基础上不断尝试写出更NB的爬虫,有

Storm【实践系列-如何写一个爬虫- 对于Protocol进行的封装】

本章描述:对于Protocol的封装 package com.digitalpebble.storm.crawler.fetcher; import com.digitalpebble.storm.crawler.util.Configuration; public interface Protocol {     public ProtocolResponse getProtocolOutput(String url) throws Exception;          public voi

也写一个简单的网络爬虫

引子 在cnblogs也混了许久,不过碍于平日工作太忙,一篇随笔也没有写过.最近经常感觉到自己曾经积累过的经验逐步的丢失,于是开通了博客,主要是记录一下自己在业余时间里玩的一些东西. 缘起 言归正传.某次在在某高校网站闲逛,看到了一些有趣的东西想要保存起来,但是却分散在各个页面,难以下手.使用baidu,google却有无法避免的搜索到此站点之外的内容.于是就想如果有一个爬虫,可以抓取指定域名的某些感兴趣的内容,不是很好.在网上简单搜索了一下,简单的都不满意,功能强大的又太复杂,就想自己写一个.