[科學上網]Node.js 種子下載器

来源:https://www.cnblogs.com/stevexu/archive/2018/10/08/9755337.html
-Advertisement-
Play Games

[科學上網]Node.js 種子下載器 慶祝 2018 國慶,製作了一個 的種子下載器。爬取頁面,根據頁面的鏈接,破解另外一個網站,下載種子文件,同時使用 模塊提高爬蟲的併發量。項目比較簡單,爬取頁面沒有使用任何爬蟲框架。 "源碼傳送門" 。 的安裝請看我的另外一篇文章, "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 // 解析 DOM
  • iconv-lite // 解決中文亂碼的問題
  • request // http 請求,圖片和種子的下載
  • socks5-http-client // socks 代理

爬取網頁策略

網頁之間,是靠鏈接聯繫在一起的,符合數據結構裡面的圖狀結構。所以,對應有如下兩種爬取策略。

  1. 爬取所有列表頁面的鏈接後,再去爬取所有詳情頁面,對應圖演算法的廣度優先遍歷。
  2. 爬取一部分列表頁面,就去爬取詳情頁面。然後再去爬取列表頁面,爬取詳情頁面,迴圈進行,對應圖演算法的深度優先遍歷。

因為是國外網站,網路可能隨時斷開,所以採用第二種策略比較好。同時,也能很快得到種子文件。為了防止重覆爬取頁面,可以將爬取頁面的鏈接作為索引。

請求代理

網站是國外網站,需要使用梯子,否則不能爬取。代理傳送門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

總結

  1. 學習中文編碼為亂碼的解決方法
  2. 學習了 request 的代理以及文件下載功能
  3. 破解種子網站的種子下載功能
  4. js 面向對象開發
  5. 爬蟲併發量解決

感謝閱讀!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><select id="test" name=""> <option value="1">text1</opti ...
  • 我是菜鳥,老鳥勿看,繼承多態等太多概念難以理解,還是從實踐中慢慢學吧!爭取能大致看懂網上的開源的代碼。 對象的組成:方法和屬性 屬性關鍵詞:靜止的,狀態 方法關鍵詞:動態的,過程,處理,帶括弧 js中的面向對象不是其他語言那樣的面向對象。 結果是數組有個number屬性和test方法,但是數組內容為 ...
  • 線上產品代碼一般是編譯過的,前端的編譯處理過程包括不限於 轉譯器/Transpilers (Babel, Traceur) 編譯器/Compilers (Closure Compiler, TypeScript, CoffeeScript, Dart) 壓縮/Minifiers (UglifyJS) ...
  • CSS作為前端開發必備基礎知識,但隨著顯示器技術發展和多種設備共存情況下,前端技術也越來越複雜,如何更好的使用css,有哪些css框架可以供選擇,他們又有什麼優缺點?本文對這一些問題進行了說明,文末有各種css框架對比的鏈接,可以供前端開發小伙伴參考 本文資源 "https://www.slides ...
  • 首先我們來認識view 改變一些特性,再來看看項目的變化 我們新增flex佈局的一些屬性,再來看看項目的變化 接下來我們來看看如果獲取屏幕的解析度 關於圖片的用法,reactNative這裡也是很神奇呢 先看效果圖(博客園裡有個人經常發這種色情圖片,然後我今天找這種線上鏈接就去他的快閃記憶體裡面隨便拿了一 ...
  • WebSocket 學習筆記 "來自我的博客" 因為項目原因需要用到雙工通信,所以比較詳細的學習了一下瀏覽器端支持的 WebSocket. 並記錄一些遇到的問題。 簡介 WebSocket 一般是指瀏覽器提供的 API 介面,允許 Web 頁面通過 WebSocket 協議與遠程主機進行雙向通信。 ...
  • 熟悉 Angular 的同學對指令肯定不會陌生,Vue中也借鑒了指令這一特性,在 Vue 中指令都是帶有 v- 的特殊屬性,那麼指令有什麼作用呢? 我的理解就是:指令是用來控制 DOM 元素的行為,例如最簡單的顯示,隱藏。 Vue 中有很多指令,在今後的學習過程總我們會逐步的學習,今天我們就來說說我 ...
  • 用JS生成動態生成表格,行、列由用戶輸入,並使表格隔行換色 方法一. 代碼: 運行結果: 輸入行數、列數,create Table: 方法二. 代碼: 運行結果: 輸入行數、列數: *僅供參考,轉載請註明 *代碼①參考:https://www.cnblogs.com/hwgok/p/5739822. ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...