nodejs下载器,通过chrome代理下载http资源
var config={
//不想访问的东西,节约流量
"404":[
"http://qidian.qpic.cn/qdbimg"
],
//奇数为需要下载的,偶数为不需要下载的
needLoad:[
//匹配需要下载的
[
"/*.js",
"/*.css",
"/*.png"
],
//匹配不需要下载的
[
"/a.js"
]
],
//修改文件保存的地方,默认按照url来的
saveFiles:[
//防止太深文件夹
["(//*/*/*/*/*/)**/","$1"],
//过滤无效文件夹字符
[/(\/\w*)\?+(\w*\/)/gi,"$1$2"]
],
//代理的端口号
port:100
}
function regDir(str){
var reg=str
if(typeof reg=="string"){
reg=reg.replace(/[\[\]\\\^\:\.\?\+]/g,function(m){
return "\\"+m;
})
reg=reg.replace(/\*\*|\*/g,function(m){
if(m=="**"){
return "[\\w\\W]*";
}else{
return "[^\\\/]*";
}
})
reg=new RegExp(reg,"gi")
}
return reg
}
String.prototype.Test=function(regStr){
var reg=regDir(regStr)
return reg.test(this)
}
String.prototype.Replace=function(regStr,fn){
var reg=regDir(regStr)
return this.replace(reg,fn);
}
var fs=require("fs")
function mkdir(filepath){
var path=require("path")
if(!fs.existsSync(path.dirname(filepath))){
mkdir(path.dirname(filepath))
}
if(!fs.existsSync(filepath)){
fs.mkdirSync(filepath)
}
}
function eachHeader (obj, fn) {
if (Array.isArray(obj.rawHeaders)) {
// ideal scenario... >= node v0.11.x
// every even entry is a "key", every odd entry is a "value"
var key = null;
obj.rawHeaders.forEach(function (v) {
if (key === null) {
key = v;
} else {
fn(key, v);
key = null;
}
});
} else {
// otherwise we can *only* proxy the header names as lowercase'd
var headers = obj.headers;
if (!headers) return;
Object.keys(headers).forEach(function (key) {
var value = headers[key];
if (Array.isArray(value)) {
// set-cookie
value.forEach(function (val) {
fn(key, val);
});
} else {
fn(key, value);
}
});
}
}
var hopByHopHeaders = [
'Connection',
'Keep-Alive',
'Proxy-Authenticate',
'Proxy-Authorization',
'TE',
'Trailers',
'Transfer-Encoding',
'Upgrade'
];
// create a case-insensitive RegExp to match "hop by hop" headers
var isHopByHop = new RegExp('^(' + hopByHopHeaders.join('|') + ')$', 'i');
//伪造http
function parse (req, server) {
var parsed = require("url").parse(req.url);
var socket = req.socket;
parsed.uri=parsed.href;
parsed.gzip=true;
// proxy the request HTTP method
parsed.method = req.method;
// setup outbound proxy request HTTP headers
var headers = {};
var hasXForwardedFor = false;
parsed.headers = headers;
eachHeader(req, function (key, value) {
var keyLower = key.toLowerCase();
if (!hasXForwardedFor && 'x-forwarded-for' === keyLower) {
// append to existing "X-Forwarded-For" header
// http://en.wikipedia.org/wiki/X-Forwarded-For
hasXForwardedFor = true;
value += ', ' + socket.remoteAddress;
}
if (isHopByHop.test(key)) {
} else {
var v = headers[key];
if (Array.isArray(v)) {
v.push(value);
} else if (null != v) {
headers[key] = [ v, value ];
} else {
headers[key] = value;
}
}
});
if (!hasXForwardedFor) {
headers['X-Forwarded-For'] = socket.remoteAddress;
}
if (null == parsed.port) {
// default the port number if not specified, for >= node v0.11.6...
// https://github.com/joyent/node/issues/6199
parsed.port = 80;
}
return parsed
}
function getPath(url){
var filename=url.Replace("(**)?*","$1").Replace("http://(**/*)","$1")
var dirname=filename.Replace("(**)/*","$1")
mkdir("www/"+dirname)
return "www/"+filename
}
var api={
parse:parse,
mkdir:mkdir,
getPath:getPath
}
/************************************/
var http = require('http');
var fs=require("fs")
var request = require('request');
var server = http.createServer();
server.listen(config.port||100, function () {
var port = server.address().port;
console.log('HTTP(s) proxy server listening on port %d', port);
});
server.on('request', function (req, res) {
var url=req.url
var arr404=config["404"]
var is404=false
arr404.forEach(function(v,k){
if(url.Test(v)){
is404=true
}
})
if(is404){
res.end()
return
}
var parsed=api.parse(req,this)
//是否下载
var isLoaded=false;
//是否下载的列表
var regArr=config.needLoad
var back=false
regArr.forEach(function(v,k){
back=!back
v.forEach(function(v2,k2){
if(url.Test(v2)){
isLoaded=back
}
})
})
//修改保存文件路径
/*
* 匹配规则
* 修改后 */
var saveFiles=config.saveFiles
// isLoaded=false
if(isLoaded){
saveFiles.forEach(function(v,k){
url=url.Replace(v[0],v[1])
})
console.log(url)
var path=api.getPath(url)
console.log(path)
//下载
var reque=request(parsed,function(err,resp,body){
if(err){
return
}
if(path.Test("/*.css")){
res.writeHead(200,{
"content-type":"text/css"
})
}
fs.createReadStream(path).pipe(res)
})
reque.pipe(fs.createWriteStream(path))
reque.on("error",function(){
console.error(url)
})
}else{
//不下载
var reque=request(parsed)
reque.pipe(res)
reque.on("error",function(){
console.error(url)
})
}
})
nodejs下载器,通过chrome代理下载http资源的更多相关文章
- IDM下载器添加支持自动下载的文件类型
不知道各位读者老爷有没有试过IDM下载器的自动下载功能,对于经常需要下载素材资源的朋友来说,一个个的选择图片或者其他什么素材来下载也是够烦的,IDM的自动下载功能可谓是十分好用,而且自动下载+批量下载 ...
- 如何在苹果电脑下载器Folx中管理下载列表
Folx是一款Mas OS专用的下载器,提供了便捷的下载管理.灵活的设置.今天小编准备跟大家聊一聊关于Folx中常见的几种下载管理方式. 一.管理任务状态栏 在Folx下载面板上,可以通过类别查看任务 ...
- 使用Python开发小说下载器,不再为下载小说而发愁 #华为云·寻找黑马程序员#
需求分析 免费的小说网比较多,我看的比较多的是笔趣阁.这个网站基本收费的章节刚更新,它就能同步更新,简直不要太叼.既然要批量下载小说,肯定要分析这个网站了- 在搜索栏输入地址后,发送post请求获取数 ...
- scrapy中的下载器中间件
scrapy中的下载器中间件 下载中间件 下载器中间件是介于Scrapy的request/response处理的钩子框架. 是用于全局修改Scrapy request和response的一个轻量.底层 ...
- 基于iOS 10、realm封装的下载器
代码地址如下:http://www.demodashi.com/demo/11653.html 概要 在决定自己封装一个下载器前,我本以为没有那么复杂,可在实际开发过程中困难重重,再加上iOS10和X ...
- .NET破解之太乐地图下载器【非暴破】
不知不觉,接触破解逆向已经三个月了,从当初的门外汉到现在的小白,这个过程只有经历过才知道其中的苦与乐: 有无知.困惑.痛苦.惊喜.彻悟.欣慰…… 有无助的软件脱壳,茫然的代码分析,有无趣的反复测试, ...
- python多进程断点续传分片下载器
python多进程断点续传分片下载器 标签:python 下载器 多进程 因为爬虫要用到下载器,但是直接用urllib下载很慢,所以找了很久终于找到一个让我欣喜的下载器.他能够断点续传分片下载,极大提 ...
- SongTaste音乐下载器
SongTaste音乐下载器 Songtaste是一个非常好的音乐推荐网站, 奈何和duomi搅合在一起, 导致下载音乐非常的麻烦, 现在写了一个简单的"下载器", 通过它可以下载 ...
- 使用Via浏览器+ADM下载器突破百度网盘下载限速
1.下载必要工具 via浏览器 ADM下载器 2.自定义 UA UA 是一串特殊字符,用来告诉所访问的网站,手机使用的操作系统及版本.CPU 类型.浏览器及版本等信息.UA 内容如下: Mozilla ...
随机推荐
- Edge 自动给数字加下划线的问题
<meta name="format-detection" content="telephone=no,email=no,address=no">
- [GO]猜数字的小游戏
随机生成四位数字,然后用户输入四位数字,然后根据提示一步步猜到随机数 package main import ( "math/rand" "time" &quo ...
- Monkey进行压力测试定位问题分析
Monkey测试的log分析,我们可以通过几个关键词来判断测试是否通过. 分析log方法一(粗糙一点): 1)Monkey finished打开LOG,查看log的最下端,是否有类似以下字段:## ...
- BZOJ 3083 遥远的国度(树链剖分+LCA)
Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...
- angular 样式属性绑定
<button (click)="onClick($event)">点我</button> <input type="> <ta ...
- Android学习笔记 TextSwitcher文本切换组件的使用
activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&qu ...
- this指针------新标准c++程序设计
背景: c++是在c语言的基础上发展而来的,第一个c++的编译器实际上是将c++程序翻译成c语言程序,然后再用c语言编译器进行编译.c语言没有类的概念,只有结构,函数都是全局函数,没有成员函数.翻 ...
- 649. Dota2 Senate
In the world of Dota2, there are two parties: the Radiant and the Dire. The Dota2 senate consists of ...
- python自带的排列组合函数
需求: 在你的面前有一个n阶的台阶,你一步只能上1级或者2级,请计算出你可以采用多少种不同的方法爬完这个楼梯?输入一个正整数表示这个台阶的级数,输出一个正整数表示有多少种方法爬完这个楼梯. 分析:提炼 ...
- Linux原理与实践
Linux 中的文件及权限 -rwxr-xr-x 1 cat animal 68 03-31 21:47 sleep.sh 三种用户角色: r 4 w 2 x 1 user ,文件的所有者 group ...