Node.js 种子下载器
Node.js 种子下载器
庆祝 2018 国庆,制作了一个 Node.js 的种子下载器。爬取页面,根据页面的链接,破解另外一个网站,下载种子文件。项目比较简单,爬取页面没有使用任何爬虫框架。项目源码
Node.js 的安装请看我的另外一篇文章,Node.js 的多版本安装。
项目初始化
新建一个文件夹 FBIWarning,在该文件夹下打开命令行 CMD 或者 git bash。运行 npm init -y,该文件夹会生成一个 package.json 文件。
安装依赖包
安装依赖包 cnpm install --save cheerio iconv-lite request socks5-http-client。每个依赖包的功能如下:
cheerio// 解析 DOMiconv-lite// 解决中文乱码的问题request// http 请求,图片和种子的下载socks5-http-client// socks 代理
爬取网页策略
网页之间,是靠链接联系在一起的,符合数据结构里面的图状结构。所以,对应有如下两种爬取策略。
- 爬取所有列表页面的链接后,再去爬取所有详情页面,对应图算法的广度优先遍历。
- 爬取一部分列表页面,就去爬取详情页面。然后再去爬取列表页面,爬取详情页面,循环进行,对应图算法的深度优先遍历。
因为是国外网站,网络可能随时断开,所以采用第二种策略比较好。同时,也能很快得到种子文件。为了防止重复爬取页面,可以将爬取页面的链接作为索引。
请求代理
网站是国外网站,需要使用梯子,否则不能爬取。代理传送门。socks5-http-client 配合 reqeust 使用,可以解决代理的问题。但是,该代理只支持 socks 代理, http(s) 代理暂不支持。
解决中文乱码的问题
目标网站的页面编码是 gbk ,而 request 依赖包的默认编码是 UTF-8,使用默认编码解码方式,会导致页面的中文变成乱码。所以得到返回数据前,去掉默认编码,就是设置编码为 encoding: null,然后使用 iconv-lite 使用 gbk 方式解码,这样就可以解决中文编码为乱码的问题,代码如下:
const request = require("request")
// 解析 dom
const cheerio = require("cheerio")
// 中文编码
const iconv = require("iconv-lite")
// 代理
const Agent = require("socks5-http-client/lib/Agent")
const COMMON_CONFIG = require("./config")
/**
* 请求页面
* @param {String} requestUrl 请求页面
*/
function requestPage(requestUrl) {
try {
return new Promise((resolve, reject) => {
if (!requestUrl) {
resolve(false)
}
request.get(
{
url: requestUrl,
agentClass: Agent,
agentOptions: {
socksPort: 13838, // 代理端口
socksHost: "127.0.0.1" // 代理 Host
},
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"
},
// 去掉默认 utf-8 解码,否则解码会乱码
encoding: null
},
function(err, response, body) {
// 防止解析报错
try {
// 统一解决中文乱码的问题
let content = iconv.decode(body, "gbk")
let $ = cheerio.load(content)
resolve($, err, response, body, content)
} catch (error) {
resolve(null)
}
}
)
})
} catch (error) {
//如果连续发出多个请求,即使某个请求失败,也不影响后面的其他请求
Promise.resolve(null)
}
}
并发请求
分页请求有很多个,可以使用递归来一个一个请求,但是写法不太好看。所以,可以使用 ES7+ 里面的 async 函数,将同步过程变为异步过程。async 要配合 await 使用,就可以将同步过程变为异步过程。详细了解 async 请看阮一峰 ES async
async function innerRecursion() {
for (let i = 1; i <= 100; i++) {
let requestUrl = "http://www.baidu.com?page=" + i // 事例网站,非爬取网站
let result = await this.requestPage(url)
}
}
一个一个请求比较慢,可以使用 Promise.all 实现并发请求。当然,也可以使用 async 模块 提高下载的并发量,有需要的可以自己去了解。这个 async 模块并非上面的 async 函数。
function innerRecursion() {
let requestUrls = []
for (let i = 1; i <= 100; i++) {
let requestUrl = "http://www.baidu.com?page=" + i // 事例网站,非爬取网站
requestUrls.push(requestUrl)
}
let promises = requestUrls.map(url => this.requestPage(url))
Promise.all(promises)
.then(results => {
// results 是一个数组,对应上面每个请求的结果
})
.catch(error => {
// 捕获请求中可能发生的错误
console.log(error)
})
}
图片下载
图片的下载非常简单,代码如下:
/**
* 下载文件
* @param {String} url 请求链接
* @param {String} filePath 文件路径
*/
function downloadFile(url, filePath) {
// try...catch 防止一个请求出错,导致程序终止 种子的下载相同
try {
if (!url || !filePath) {
return false
}
request
.get({
url,
agentClass: Agent,
agentOptions: {
socksPort: 13838, // 代理端口
socksHost: "127.0.0.1" // 代理 Host
},
headers: {
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"
}
}
})
.pipe(fs.createWriteStream(filePath))
} catch (error) {
console.log(error)
}
}
破解网站种子下载
解析详情页面,只能得到类似 http://www.jandown.com?ref=VENU794 的链接,需要破解该网站的种子下载。查看网站的种子下载方式,就是一个 post 请求,后端就会返回种子文件。刚开始的时候,不熟悉服务端的表单提交方式,导致文件一直得不到,后来详细查看了 request 的官文文档,发现是自己写错了。结合上面的图片下载,种子的下载方式自然就有了,代码如下:
/**
* 下载种子链接
* @param {String} childDir // 子目录
* @param {String} downloadUrl // 下载种子地址
*/
function downloadTorrent(childDir, downloadUrl) {
try {
// 解析出链接的 code 值
let code = querystring.parse(downloadUrl.split("?").pop()).ref
if (!code || !childDir) {
return false
}
// 发出 post 请求,然后接受文件即可
request
.post({
url: "http://www.jandown.com/fetch.php",
agentClass: Agent,
agentOptions: {
socksPort: 13838, // 代理端口
socksHost: "127.0.0.1" // 代理 Host
},
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"
},
formData: {
code
}
})
.pipe(fs.createWriteStream(childDir + "/" + code + ".torrent"))
} catch (error) {
console.log(error)
}
}
面向对象
刚开始是使用面向过程的方式写的,后来发现代码太重复了,所以采用 OOP 改写了整个代码。详细了解 javaScript Class 请看阮一峰 ES class
总结
- 学习中文编码为乱码的解决方法
- 学习了
request的代理以及文件下载功能 - 破解种子网站的种子下载功能
- js 面向对象开发
- 爬虫并发量解决
感谢阅读!
Node.js 种子下载器的更多相关文章
- Node.js包管理器Yarn的入门介绍与安装
FAST, RELIABLE, AND SECURE DEPENDENCY MANAGEMENT. 就在昨天, Facebook 发布了新的 node.js 包管理器 Yarn 用以替代 npm .咱 ...
- Node.js包管理器:
Node.js包管理器: 当我们要把某个包作为工程运行的一部分时,通过本地模式获取,如果要在命令行下使用,则使用全局模式安装 使用全局模式安装的包并不能直接在JavaScript文件中用require ...
- node.js之调试器
node.js之调试器 1.在命令行窗口中,可以使用"node debug" 命令来启用调试器,代码如下: node debug<需要被执行的脚本文件名> 接下来根据一 ...
- Node.js的下载、安装、配置、Hello World、文档阅读
Node.js的下载.安装.配置.Hello World.文档阅读
- Folx种子下载器怎么管理下载任务
对于喜欢追剧的用户来说,同时下载好几部剧是司空见惯的事情.但有时候,有些剧比较好看或者热度比较高时,就会希望优先将其下载下来. 对于使用Folx种子下载器的用户来说,可以结合使用下载列表+最大活动数的 ...
- npm --- Node.js包管理器
目录 1. 安装Node.js 2. 运行npm 3. npm介绍 3.1 安装插件 3.2 更新插件 3.3 卸载插件 3.4 查看当前目录中的插件列表 4. 使用cnpm 4.1 安装 npm( ...
- Node.js 包管理器 NPM 讲解
包管理器又称软件包管理系统,它是在电脑中自动安装.配制.卸载和升级软件包的工具组合,在各种系统软件和应用软件的安装管理中均有广泛应用.对于我们业务开发也很受益,相同的东西不必重复去造轮子. 每个工具或 ...
- 9.Node.js 包管理器npm
npm 是 Node.js 官方提供的包管理工具, 用于 Node.js包的发布.传播.依赖控制 安装 express ==> 流行的基于Node.js的Web开发框架,可以快速地搭建一个完整 ...
- node.js服务器端下载、上传文件
使用request 下载文件: 安装依赖: npm i requestsourceUrl下载源,targetUrl保存路径 async function downLoadFile(sourceUrl, ...
随机推荐
- C# 获取版本号
Text = Text + " [V." + Assembly.GetExecutingAssembly().GetName().Version + "]";
- EXTJS4.2 内存中操作表格数据时,删除表格数据,行号不连续解决
需要重新刷新下表格的view => grid.view.refresh();
- UOJ#416. 【APIO2018】铁人两项
原文链接www.cnblogs.com/zhouzhendong/p/UOJ416.html 前言 完了完了SB选手Tarjan写挂. 题解 考虑先Tarjan缩个点双建个圆方树. 然后发现,确定起点 ...
- 线程池ThreadPoolTaskExecutor配置说明
一般实际开发中经常用到多线程,所以需要使用线程池了, ThreadPoolTaskExecutor通常通过XML方式配置,或者通过Executors的工厂方法进行配置. XML方式配置代码如下:交给 ...
- MDK5 设置project targents?如何实现的有知道的请共享一下谢谢感激不尽!!!!
就在刚刚阅读NRF51822相关的文档时遇到问题,官方给出了一份模板,我从我安装的example中找出了官方的列程,看到是soft config的方式配置的,于是根据列程的配置,自己新建了一个工程之后 ...
- centos7.x 安装 fastDFS
环境准备 使用的系统软件 名称 说明 centos 7.x libfatscommon FastDFS分离出的一些公用函数包 FastDFS FastDFS本体 fastdfs-nginx-modul ...
- 工作流——activiti
1.导入依赖 <!-- activiti工作流 --> <dependency> <groupId>org.activiti</groupId> < ...
- Alpha冲刺(4/10)——2019.4.26
作业描述 课程 软件工程1916|W(福州大学) 团队名称 修!咻咻! 作业要求 项目Alpha冲刺(团队) 团队目标 切实可行的计算机协会维修预约平台 开发工具 Eclipse 团队信息 队员学号 ...
- cn microsoft hyper-v server 2016 安装笔记
英文版,先用,随后 中文版再出笔记 不知道是不是 WINDOWS 7 USB DVD TOOLS 没有更新,怎么做不了优盘启动,只能找个 替代工具RUFUS.
- BZOJ.5305.[HAOI2018]苹果树(组合 计数)
LOJ BZOJ 洛谷 BZOJ上除了0ms的Rank1啦.明明这题常数很好优化的. 首先,\(n=1\)时有\(2\)个位置放叶子,\(n=2\)时有\(3\)个... 可知\(n\)个点的有标号二 ...