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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...