1. 程式人生 > >用Python獲取磁力種子

用Python獲取磁力種子

陳鍵冬,Python中文社群專欄作者,pyecharts開源專案核心開發者,github id:chenjiandongx

本文專案地址:github.com/chenjiandongx/magnet-dht

磁力連結

現在我們使用迅雷等工具下載資源的時候,基本上都只需要一個叫做磁力連結的東西就可以了,非常方便。

640?wx_fmt=jpeg

磁力連結是對等網路中進行資訊檢索和下載文件的電腦程式。和基於“位置”連線的統一資源定位符不同,磁力連結是基於元資料檔案內容,屬於統一資源名稱。也就是說,磁力連結不基於文件的 IP 地址或定位符,而是在分散式資料庫中,通過雜湊函式值來識別、搜尋來下載文件。因為不依賴一個處於啟動狀態的主機來下載文件,所以特別適用沒有中心伺服器的對等網路。

磁力連結格式類似於 :

magnet:?xt=urn:btih:E7FC73D9E20697C6C440203F5884EF52F9E4BD28

分解一下這個連結

  • magnet:協議名。

  • xt:exact topic 的縮寫,表示資源定位點。BTIH(BitTorrent Info Hash)表示雜湊方法名,這裡還可以使用 SHA1 和 MD5。這個值是檔案的識別符號,是不可缺少的。

一般來講,一個磁力連結只需要上面兩個引數即可找到唯一對應的資源。也有其他的可選引數提供更加詳細的資訊。

  • dn:display name 的縮寫,表示向用戶顯示的檔名。

  • tr:tracker 的縮寫,表示 tracker 伺服器的地址。

  • kt: 關鍵字,更籠統的搜尋,指定搜尋關鍵字而不是特定檔案。

  • mt:檔案列表,連結到一個包含磁力連結的元檔案 (MAGMA - MAGnet MAnifest)。

種子/DHT

通過磁力就可以獲取種子檔案從而進行下載,這跟直接使用種子下載時一個道理的,只是少了從磁力到種子檔案的一個過程而已。

640?wx_fmt=jpeg

BitTorrent 協議的種子檔案可以儲存一組檔案的元資料。這種格式的檔案被 BitTorrent 協議所定義。副檔名一般為“.torrent”。BitTorrent 使用”分散式雜湊表”(DHT)來為無 tracker 的種子(torrents)儲存 peer 之間的聯絡資訊。這樣每個 peer 都成了 tracker。這個協議基於 Kademila 網路並且在 UDP 上實現。

DHT 由節點組成,它儲存了 peer 的位置。BitTorrent 客戶端包含一個 DHT 節點,這個節點用來聯絡 DHT 中其他節點,從而得到 peer 的位置,進而通過 BitTorrent 協議下載。

  • peer: 一個 TCP 埠上監聽的客戶端/伺服器,它實現了 BitTorrent 協議。

  • 節點: 一個 UDP 埠上監聽的客戶端/伺服器,它實現了 DHT(分散式雜湊表) 協議。 如果對 DHT 協議感興趣的話一定要看下 DHT 協議 的具體內容,這裡有 中文翻譯版本。(想要徹底讀懂專案的話一定要先了解該協議,程式碼都是基於該協議實現的)

640?wx_fmt=gif

務實的實踐

專案來源 

一般來講到 Python 爬取,大家的第一印象可能就是 requests/aiohttp,或者是 scrapy/pyspider 等爬蟲框架。基本上都是從指定的 HTML 頁面爬取資訊。我有一個專案 torrent-cli(github.com/chenjiandongx/torrent-cli) 就是一個從資源網站上爬取磁力資訊的工具。

640?wx_fmt=jpeg

然而我想自給自足獲取磁力種子,Google 了一番,發現大家基本上的程式碼都是從 simDHT(github.com/fanpei91/simDHT)這個專案來的,首先這個專案很棒,但是有個問題就是程式碼實現細節基本沒有一行註釋且不相容 Python3。而很多網上同類的程式碼基本上也是對這個照搬....

所以我知道我要開始幹活了

640?wx_fmt=gif

經過一波 happy coding 之後

640?wx_fmt=gif

專案結構

核心程式碼

  • crawler.py

從 DHT 網路中獲取磁力連結。主要是利用一些大型的伺服器 tracker,冒充 DHT 節點,使用 UDP 協議加入到 DHT 網路中一波搜尋以及和其他節點搞好關係,讓他們也分享我點資源。磁力資料存放在了 redis,利用 redis 的集合特性來去重。使用了多執行緒/多程序,用於提高爬取效率。在我的本地機器(i7-7700HQ/16G 記憶體/8M 網速)跑了一下,效果還不錯,4 小時爬了 100 萬條磁力連結。

  1. $ redis-cli

  2. 127.0.0.1:6379> scard magnets

  3. (integer)1137627

然後程式碼推送到我那臺效能強悍 1 核/2G 記憶體/1M 網速阿里雲伺服器跑一下,哎....

640?wx_fmt=jpeg

  • magnettotorrent_aria2c.py 利用 aria2 將磁力連結轉換為種子檔案。嘗試了一些其他的方式將磁力轉換為種子,但效果好像都不怎麼理想。使用過 libtorrent 的 Python 版本,不知道是我開啟方式不對還是它本來效率就不高,反正愣是一個種子都沒有轉換成功。

最後兜兜轉轉用到了 aria2 發現效率還可以。這裡利用多執行緒跑一個命令。所以要先把 aria2 安裝到你的 PATH 中,具體參考官網介紹。

  • parse_torrent.py 解析種子檔案內容,同樣也是利用了 bencoder 進行解碼。有了種子我們當然要看看到底是些什麼資源了啦。你說世界就是這麼小,在我解析出來的幾百個種子檔案中,居然有幾個都是來自那個以 2的10次方為標誌的社群。

640?wx_fmt=jpeg

有圖有真相

640?wx_fmt=jpeg

不過我還是希望大家銘記下面這 24 字箴言

640?wx_fmt=jpeg

輔助程式碼

  • database.py:封裝了關於 redis 的資料操作,主要是利用其集合資料結構。

  • utils.py:一些工具函式

如何使用

獲取原始碼及安裝依賴環境

  1. $ git clone https://github.com/chenjiandongx/magnet-dht.git

  2. $ cd magnet-dht

  3. $ pip install -r requirements.txt# 確保已經安裝好 redis,redis 的具體配置可以在 database.py 裡面修改。

執行專案

  1. # 至於程序數量可以在 crawler.py 進行調整$ python manage.py -h

  2. usage: manage.py [-h][-s][-m][-p]

  3. start manage.py with flag.

  4. optional arguments:

  5. -h,--help  show this help message andexit-s          run start_server func.

  6. -m          run magnet2torrent func

  7. -p          run parse_torrent func

深刻的感悟

自我學程式設計以來,我一直都是屬於興趣驅動的,對某種技術感興趣的話就會花時間去研究去嘗試。想成為一個有趣的人,去做一些有趣的事,真心覺得能把腦海裡的想法轉變為程式碼實現是件很棒的事,即使可能這件事在別人看來並沒有什麼了不起。技術發展變化總是那麼快,不緊跟著可能不小心就掉隊了。所以希望每個真心熱愛程式設計的人都能不忘初心,永遠保持對新技術的熱情,永遠能從編碼中找到樂趣。

640?wx_fmt=png

640?wx_fmt=gif

Python中文社群作為一個去中心化的全球技術社群,以成為全球20萬Python中文開發者的精神部落為願景,目前覆蓋各大主流媒體和協作平臺,與阿里、騰訊、百度、微軟、亞馬遜、開源中國、CSDN等業界知名公司和技術社群建立了廣泛的聯絡,擁有來自十多個國家和地區數萬名登記會員,會員來自以公安部、工信部、清華大學、北京大學、北京郵電大學、中國人民銀行、中科院、中金、華為、BAT、谷歌、微軟等為代表的政府機關、科研單位、金融機構以及海內外知名公司,全平臺近20萬開發者關注。

640?wx_fmt=jpeg

▼ 點選下方閱讀原文免費成為社群會員