[科學上網]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
  • 移動開發(一):使用.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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...