网页抓取解密(data模块详细解析(图) )

优采云 发布时间: 2021-09-21 16:07

  网页抓取解密(data模块详细解析(图)

)

  最近 node.js 一个比较出名的 http request 模块停止维护了。其实这个模块已经变得非常臃肿,模块依赖过多,体积过大,接口不统一。

  其实现在node.js的http模块已经非常完善,几行代码就能自己写一个,比如:

  Node.js网页抓取:一个最简单的http请求客户端示例(request client)

  不过上面的示例并不支持post和文件下载,只要稍加改动即可。

  源代码

  var http = require('http')<br />var https = require('https')<br />var url = require('url')<br />var qs = require('querystring')<br /><br />var filters = []<br /><br />/*<br />settings => {<br /> url: '/sync/list'<br /> , data: { a,b,c } / stream<br /> , type: 'qs' / 'json'<br /> , dataType: 'json' / 'qs' / 'raw' / 'stream'<br />}<br /><br />cb => (err, res, {})<br />*/<br />var request = function(settings, cb) {<br /> if (typeof settings == 'string') {<br /> settings = { url: settings }<br /> }<br /><br /> settings.headers = settings.headers || {}<br /><br /> var data = settings.data || settings.body || settings.json<br /> var dataType = settings.dataType<br /> var stream<br /> var rawData<br /><br /> if (data && data.pipe) {<br /> stream = data<br /> // rawData = data<br /> } else if (typeof data == 'object') {<br /> if (settings.type == 'qs') {<br /> rawData = qs.stringify(data)<br /> } else {<br /> rawData = JSON.stringify(data)<br /> settings.headers['content-type'] = 'application/json'<br /> }<br /> } else if (data) {<br /> rawData = data<br /> }<br /><br /> if (rawData) {<br /> rawData = Buffer.from(rawData)<br /> settings.headers['content-length'] = rawData.length<br /> }<br /><br /> var reqUrl = settings.url<br /> var urlObj = url.parse(reqUrl)<br /><br /> var options = {<br /> hostname : urlObj.hostname<br /> , port : urlObj.port<br /> , path : urlObj.path<br /> , method : settings.method || ((stream || rawData) ? 'POST' : 'GET')<br /> , headers : settings.headers<br /> }<br /><br /> for (var i = 0; i < filters.length; i++) {<br /> var filter = filters[i]<br /> filter(settings, options)<br /> }<br /><br /> var requestHandler = function(res) {<br /> var receives = []<br /> var err = null<br /> var statusCode = res.statusCode<br /> var headers = res.headers<br /><br /> //重定向<br /> if ((statusCode == 302 || statusCode == 301) && headers.location) {<br /> options.url = headers.location<br /> request(options, cb)<br /> return<br /> }<br /><br /> if (statusCode > 300) {<br /> err = new Error('Request Failed. Status Code: ' + res.statusCode + ' ' + reqUrl)<br /> }<br /><br /> //doesn't parse data<br /> if (dataType == 'stream' || settings.stream) {<br /> cb && cb(err, res, {})<br /> return<br /> }<br /><br /> res.on('data', function(chunk) {<br /> receives.push(chunk)<br /> })<br /><br /> res.on('end', function() {<br /> var resData = Buffer.concat(receives).toString()<br /> if (dataType != 'raw') {<br /> try {<br /> resData = dataType == 'qs'<br /> ? qs.parse(resData)<br /> : JSON.parse(resData)<br /> } catch (e) { }<br /> }<br /><br /> cb && cb(err, res, resData)<br /> })<br /> }<br /><br /> var req = urlObj.protocol == 'https:'<br /> ? https.request(options, requestHandler)<br /> : http.request(options, requestHandler)<br /><br /> req.on('error', function(e) {<br /> cb && cb(e, null, {})<br /> })<br /><br /> if (stream) {<br /> stream.pipe(req)<br /> } else {<br /> rawData && req.write(rawData)<br /> req.end()<br /> }<br />}<br /><br />var addFilter = function(filter) {<br /> if (typeof filter == 'function') {<br /> filters.push(filter)<br /> } else {<br /> console.log('request middware is not a function')<br /> }<br />}<br /><br />module.exports = {<br /> request : request<br /> , use : addFilter<br />}

  参数

  请求的网址: url: '/sync/list'<br />请求POST的数据,如果没有则为GET: data: { a,b,c } / stream<br />请求的数据类型: type: 'qs' / 'json'<br />返回的数据类型: dataType: 'json' / 'qs' / 'raw' / 'stream'

  使用方法

  模拟GET

  const request = require('./request').request<br /><br />request({ url: 'http://ourjs.com/home' }, function(err, response, data) {<br /> console.log(data)<br />})

  模拟POST

  指定 data 即可:

  request({ url: 'http://ourjs.com/home', data: { abc: 1 } }, function(err, response, data) {<br /> console.log(data)<br />})

  下载流文件

  将请求文件下载到本地,使用流可避免使用进程的缓冲区,可下载大文件

  const fs = require('fs')<br /><br />request({ url: 'http://ourjs.com/home', dataType: 'stream' }, function(err, response, data) {<br /> let ws = fs.createWriteStream('./ourjs.text')<br /> response.pipe(ws)<br />})

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线