Node.js 種子下載器

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

慶祝 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
更多相關文章
  • 現如今,數據增長速度快於處理速度,唯一的解決方案是在大型集群上並行化,而且這種技術以及廣泛應用於企業和網路行業。本章主要內容有:講解數據流與傳統的網路編程的區別、MapReduce的局限性、Spark computing engine、Matrix operations on Spark等。 資源下 ...
  • 很多初學者在剛剛接觸大數據的時候會有很多疑惑,比如對MapReduce、Storm、Spark三個計算框架的理解經常會產生混亂。 哪一個適合對大量數據進行處理?哪一個又適合對實時的流數據進行處理?又該如何來區分他們呢? 我對比整理了這3個計算框架的基本知識,大家可以瞭解一下以便對這個3個計算框架有一 ...
  • 作者:天山老妖S 鏈接:http://blog.51cto.com/9291927 一、字元集與編碼 1、字元集簡介 字元(Character)是各種文字和符號的總稱,包括各國家文字、標點符號、圖形符號、數字等。字元集(Character set)是多個字元的集合,字元集種類較多,每個字元集包含的字 ...
  • 前面在介紹列表視圖和網格視圖時,它們的適配器代碼都存在視圖持有者ViewHolder,因為Android對列表類視圖提供了回收機制,如果某些列表項在屏幕上看不到了,則系統會自動回收相應的視圖對象。隨著用戶的下拉或者上拉手勢,已經被回收的列表項要重新載入到界面上,倘若每次載入都得從頭創建視圖對象,勢必 ...
  • 下麵舉Android的Browser源碼通過git保存到github上 首先在github.com官網new repository一個倉庫 在Repository name哪裡填入Browser然後創建 這時候會生成一個地址,這個就是你的倉庫地址。 例如我的:https://github.com/g ...
  • How to get out of Fast Factory Boot Mode(FFBM). ...
  • ListView現在已經很少被使用,但還是在這裡列出來說一下,有時候我們僅僅需要改變listView的某個Item,如果調用adapter的notifyDataSetChanged()方法效率不高,並且可能會出現內容閃動,那麼我們怎麼刷新某一個特定的item呢? 在這裡我們以刷新第一個item為例, ...
  • 本文主要介紹Flutter佈局中的LimitedBox、Offstage、OverflowBox、SizedBox四種控制項,詳細介紹了其佈局行為以及使用場景,並對源碼進行了分析。 ...
一周排行
    -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# ...