【新手向】使用nodejs抓取百度贴吧内容
参考教程:https://github.com/alsotang/node-lessons 1~5节
1. 通过superagent抓取页面内容
superagent
.get('http://www.cnblogs.com/wenruo/')
.end(function(err, res) {
if (err) {
reject(err)
} else {
console.log(res.text)
}
})
OK 这样就获得了一份HTML代码。
因为获取HTML是异步的,所以我们封装一个函数,返回一个Promise。
// 获取页面html
function getHTML(url) {
return new Promise(function(resolve, reject) {
superagent.get(url)
.end(function(err, res) {
if (err) {
reject(err)
} else {
resolve(res.text)
}
})
})
}
2. 通过cheerio筛选页面数据
总不能通过正则一点一点匹配出数据吧,有这样一个库: cheerio( https://github.com/cheeriojs/cheerio ),有了它,我们可以像jQuery一样轻松的从这个HTML代码中获取需要数据。
现在随便找了一个贴吧的帖子。
因为我们要获取一个帖子的全部内容,所以要首先要获取帖子的页数,然后分别爬取每一页的内容。通过检查元素找到数据对应的html中的位置,找到所对应的一个类 l_reply_num 然后发现其下有两个span,我们获取第二个的数据,就是总页数。

代码如下,这里通过 + 将字符串转为数字。
function getPage(html) {
let $ = cheerio.load(html)
return +$('.l_reply_num span').eq(1).text()
}
其他的数据,如标题,昵称,层数等,都可以通过同样的方法获取。
3. 控制并发数量
贴吧的高楼可以有几百上千页,我们能通过 pages.forEach(page => { getHTML(page) }) 同时发起多个异步请求获取数据,但是,网站有可能会因为你发出的并发连接数太多而当你是在恶意请求,把你的 IP 封掉。
这时我们可以通过 async ( https://github.com/caolan/async ) 来实现控制并发的数量,使用方法也很简单:
var async = require("async")
async.mapLimit(urls, 5, function(url, callback) {
const response = fetch(url)
callback(response.body)
}, (err, results) => {
if (err) throw err
// results is now an array of the response bodies
console.log(results)
})
通过遍历数组,分别对其中的每一项发起请求,5为控制的并发数量。results是callback中返回数据的集合。
当然上面的代码假设fetch是同步函数了,否则callback应该放在回调函数里面。
4. 结果保存到文件
得到的数据很大,总不能在控制台看,一定要放到文件里。
function writeFile(filename, content, cb) {
fs.writeFile(filename, content, function(err) {
if (err) {
return console.error(err);
}
cb && cb()
})
}
包含三个参数,文件名,存储内容和回调函数。
整体代码如下:
let superagent = require('superagent')
let cheerio = require('cheerio')
let async = require('async')
let fs = require('fs')
// 获取页面html
function getHTML(url) {
return new Promise(function(resolve, reject) {
superagent.get(url)
.end(function(err, res) {
if (err) {
reject(err)
} else {
resolve(res.text)
}
})
})
}
// 获取帖子页数
function getPage(html) {
let $ = cheerio.load(html)
return +$('.l_reply_num span').eq(1).text()
}
// 获取帖子标题
function getTitle(html) {
let $ = cheerio.load(html)
return $('.core_title_txt').text()
}
// 获取帖子一页内容
function getOnePage(url) {
return getHTML(url).then(html => {
let result = []
let $ = cheerio.load(html)
$('#j_p_postlist .l_post').each(function(idx, element) {
let $element = $(element)
let name = $element.find('.d_name a').text()
let content = $element.find('.d_post_content').text()
let floor = $element.find('.tail-info').eq($element.find('.tail-info').length-2).text()
let time = $element.find('.tail-info').eq($element.find('.tail-info').length-1).text()
name = name.replace(/[\s\r\t\n]/g, '')
content = content.replace(/[\s\r\t\n]/g, '')
if (floor) {
result.push(`${floor}(${name}/${time})\n${content}\n\n`)
}
})
return result.join('')
}, err => {
console.error(err)
})
}
// 将内容写入到文件
function writeFile(filename, content, cb) {
fs.writeFile(filename, content, function(err) {
if (err) {
return console.error(err);
}
cb && cb()
})
}
function getContent(url) {
console.log('抓取中...')
// 帖子后面可能会加 只看楼主 和 页码 选项 这里只添加只看楼主选项 将页码项删除
let hasSeeLZ = false
if (url.includes('?')) {
let search = url.split('?')[1].split('&')
url = url.split('?')[0]
for (let query of search) {
if (query.includes('see_lz')) {
hasSeeLZ = true
url = url + '?' + query
break
}
}
}
// 开始抓取数据
getHTML(url).then(html => {
let page = getPage(html)
let title = getTitle(html) + (hasSeeLZ ? ' -- [只看楼主]' : '')
// 控制最大并发为 5
async.mapLimit([...new Array(page).keys()], 5, function(idx, callback) {
let pageUrl = url + (hasSeeLZ ? '&' : '?') + 'pn=' + (idx+1)
getOnePage(pageUrl).then(res => {
callback(null, res)
})
}, function(err, res) {
if (err) {
return console.error(err)
}
writeFile('result.txt', title + '\n\n' + res.join(''), () => { console.log('抓取完成!') })
})
})
}
let queryUrl = 'https://tieba.baidu.com/p/3905448690?see_lz=1'
getContent(queryUrl)
效果展示(真的是随便找的贴 内容没看过……):
原贴内容:

抓取结果:

【新手向】使用nodejs抓取百度贴吧内容的更多相关文章
- Python3---爬虫---抓取百度贴吧
前言 该文章主要描述如何抓取百度贴吧内容.当然是简单爬虫实现功能,没有实现输入参数过滤等辅助功能,仅供小白学习. 修改时间:20191219 天象独行 import os,urllib.request ...
- PHP网络爬虫实践:抓取百度搜索结果,并分析数据结构
百度的搜索引擎有反爬虫机制,我先直接用guzzle试试水.代码如下: <?php /** * Created by Benjiemin * Date: 2020/3/5 * Time: 14:5 ...
- Python抓取百度百科数据
前言 本文整理自慕课网<Python开发简单爬虫>,将会记录爬取百度百科"python"词条相关页面的整个过程. 抓取策略 确定目标:确定抓取哪个网站的哪些页面的哪部分 ...
- python3 - 通过BeautifulSoup 4抓取百度百科人物相关链接
导入需要的模块 需要安装BeautifulSoup from urllib.request import urlopen, HTTPError, URLError from bs4 import Be ...
- selenium-java web自动化测试工具抓取百度搜索结果实例
selenium-java web自动化测试工具抓取百度搜索结果实例 这种方式抓百度的搜索关键字结果非常容易抓长尾关键词,根据热门关键词去抓更多内容可以用抓google,百度的这种内容容易给屏蔽,用这 ...
- C#.Net使用正则表达式抓取百度百家文章列表
工作之余,学习了一下正则表达式,鉴于实践是检验真理的唯一标准,于是便写了一个利用正则表达式抓取百度百家文章的例子,具体过程请看下面源码: 一:获取百度百家网页内容 public List<str ...
- 用PHP抓取百度贴吧邮箱数据
注:本程序可能非常适合那些做百度贴吧营销的朋友. 去逛百度贴吧的时候,经常会看到楼主分享一些资源,要求留下邮箱,楼主才给发. 对于一个热门的帖子,留下的邮箱数量是非常多的,楼主需要一个一个的去复制那些 ...
- Python爬虫之小试牛刀——使用Python抓取百度街景图像
之前用.Net做过一些自动化爬虫程序,听大牛们说使用python来写爬虫更便捷,按捺不住抽空试了一把,使用Python抓取百度街景影像. 这两天,武汉迎来了一个德国总理默克尔这位大人物,又刷了一把武汉 ...
- python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容
python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...
随机推荐
- 《Java并发编程的艺术》Java内存模型(三)
Java内存模型 一.Java内存模型的基础 1.并发编程模型的两个关键问题: 两个关键问题,线程之间如何通信和如何同步.两种方式,共享内存和消息传递.Java里线程的通信是通过共享内存,线程的同步是 ...
- mysql8 出现1521错误解决方法
ALTER USER 'root'@'localhost' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER; #修改加密规则 ALTER USER 'ro ...
- Spring-MVC运行原理
一. Spring-MVC的对象初始化,即 bean放入context的beanFactory中. 1. 对象的初始化工作主要在org.springframework.web.servlet.Fram ...
- mac mysql5.7.17修改root初始密码(知道初始密码)
最近在mac上装个mysql可以说是麻烦死了,在这里就说说修改初始密码吧! 刚开始的时候不知道怎么修改,于是上网百度,网上几乎都是说要先执行命令mysqld_safe --skip-grant-tab ...
- Cordova配置与WebApp混合开发环境配置
好久都没来更新随笔了,这阵子比较忙,不过还是在不断的学习当中,今天给大家分享一下Cordova的配置与搭建WebApp混合开发环境的配置. 准备好了吗?让我们一步步来咯!!! 1.配置JDK环境 用的 ...
- call和apply(学习笔记)
call() call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表). 语法: function.call(thisArg, arg1, arg2, ...) 参 ...
- MIUI 10以上版本通用线刷ROOT方法
1.高版本系统解锁 (解锁工具下载) http://www.miui.com/unlock/index.html 注意事项:登陆解锁工具的账号必须是登陆小米手机的账号 解锁步骤在解锁工具上有说明,就两 ...
- Appium系列文章(1)获取appPackage和appActivity
appPackage和appActivity 进行appium自动化测试非常重要的两个参数,我们所测试的APP不同,这两个参数肯定也是不一样的.那如何快速的获取这APP的这两个参数呢? 通过cmd命令 ...
- JavaScript基础视频教程总结(121-130章)
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- 《笔记篇》非JS方法跳转到一个新页面,主要防止客户端禁止浏览器JS以后的跳转异常
用非JS方法打开一个新页面,主要防止客户端禁止浏览器JS以后的跳转失效 <meta http-equiv="refresh" content="0; url=htt ...