├── .gitignore ├── LICENSE ├── README.md ├── requirements.txt ├── setup.cfg ├── setup.py └── torrent.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | /cup/ 6 | # C extensions 7 | *.so 8 | /data_/ 9 | .idea 10 | # Distribution / packaging 11 | .Python 12 | env/ 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *,cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # IPython Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # dotenv 80 | .env 81 | 82 | # virtualenv 83 | venv/ 84 | ENV/ 85 | 86 | # Spyder project settings 87 | .spyderproject 88 | 89 | # Rope project settings 90 | .ropeproject 91 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2018 chenjiandongx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 磁力获取器命令行工具 2 | 3 | [![PyPI version](https://badge.fury.io/py/torrent-cli.svg)](https://badge.fury.io/py/torrent-cli) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 4 | 5 | 作为一个搞代码的,找资源这种事肯定不能像普通人一样打开百度盲目查找,你需要写个爬虫工具来帮你完成这件事情啦! 6 | 7 | ### 兼容环境 8 | Windows/Linux/MacOs 9 | 10 | 11 | ### 安装 12 | #### pip 安装 13 | ``` 14 | $ pip install torrent-cli 15 | ``` 16 | 17 | #### 源码安装 18 | ``` 19 | $ git clone https://github.com/chenjiandongx/torrent-cli.git 20 | $ cd torrent-cli 21 | $ pip install -r requirements.txt 22 | $ python setup.py install 23 | ``` 24 | 25 | 26 | ### 如何使用 27 | ``` 28 | $ torrent-cli 29 | usage: torrent-cli [-h] [-n NUM] [-s SORT_BY] [-o OUTPUT] [-p] [-v] 30 | [KEYWORD [KEYWORD ...]] 31 | 32 | Magnets-Getter CLI Tools. 33 | 34 | positional arguments: 35 | KEYWORD magnet keyword. 36 | 37 | optional arguments: 38 | -h, --help show this help message and exit 39 | -n NUM, --num NUM magnet number.(default 10) 40 | -s SORT_BY, --sort-by SORT_BY 41 | 0: Sort by date,1: Sort by size. 2: Sort by hot- 42 | rank.(default 0) 43 | -o OUTPUT, --output OUTPUT 44 | output file path, supports csv and json format. 45 | -p, --pretty-oneline show magnets info with one line. 46 | -v, --version version information. 47 | ``` 48 | 49 | 50 | #### 示例 51 | 52 | **根据单关键字搜索** 53 | ``` 54 | $ torrent-cli 战狼2 55 | Crawling data for you..... 56 | 磁链: magnet:?xt=urn:btih:80B24033541A8DE529876488E68DCD707B074990 57 | 名称: 战狼2.2017.tc720p.中英双字.制作@卡其,更多免费资源关注微信公众号 :卡其影视控 58 | 大小: 829.0 MB 59 | 日期: 2018-05-15 60 | 热度: 1 61 | 62 | 磁链: magnet:?xt=urn:btih:CC3854CACBB5434E03EFF39C693B20223E0AA39D 63 | 名称: [hao4k.com]战狼2.4k.wolf.warriors.ii.2017.hk.2160p.uhd.blu-ray.hevc.truehd.atmos.7.1 64 | 大小: 56.8 GB 65 | 日期: 2018-05-14 66 | 热度: 25 67 | 68 | 磁链: magnet:?xt=urn:btih:F0BAFA381B258540374F854688CFFC7A590596F0 69 | 名称: 2017战狼2幕后全纪实hd720p中字.mp4 70 | 大小: 148.3 MB 71 | 日期: 2018-03-11 72 | 热度: 5 73 | 74 | 磁链: magnet:?xt=urn:btih:E7FC73D9E20697C6C440203F5884EF52F9E4BD28 75 | 名称: 战狼2.wlf.wrrirs.2.2017.hd720p.x264.aac-国语中字-rarbt 76 | 大小: 2.2 GB 77 | 日期: 2018-03-11 78 | 热度: 3 79 | 80 | 磁链: magnet:?xt=urn:btih:B8E5C85B5B368060AB245AC5E434981B0D5543CA 81 | 名称: 战狼2.字幕修复版.wolf.warriors.ii.2017.bd1080p.x264.dts-hd.ma.7.1.mandarin&english.chs-eng.mp4bafans 82 | 大小: 12.4 GB 83 | 日期: 2018-02-23 84 | 热度: 15 85 | 86 | 磁链: magnet:?xt=urn:btih:D6A5598C03C3123038DB6CAA04AE36D90BB569C6 87 | 名称: 战狼2.wolf.war[email protected]ourbits 88 | 大小: 35.0 GB 89 | 日期: 2018-02-22 90 | 热度: 16 91 | 92 | 磁链: magnet:?xt=urn:btih:5FE0D9709B9578DBD68BAAB949E00C502C703DE3 93 | 名称: [战狼2wolf.warrior.2][bluray-720p.mkv][3.42gb][国英双语] 94 | 大小: 3.4 GB 95 | 日期: 2018-02-22 96 | 热度: 25 97 | 98 | 磁链: magnet:?xt=urn:btih:5DFBF035D2CFAB3E04373C92A6463358ED5DA4E7 99 | 名称: 战狼2.超清国语中字.mp4 100 | 大小: 1.8 GB 101 | 日期: 2018-02-22 102 | 热度: 3 103 | 104 | 磁链: magnet:?xt=urn:btih:E478E2A78ECBD02C0AFC92D6E1552C09C834B43C 105 | 名称: 战狼2.wolf.warriors.ⅱ.2017.1080p.web-dl.x264.aac.mp4 106 | 大小: 2.8 GB 107 | 日期: 2018-02-22 108 | 热度: 54 109 | 110 | 磁链: magnet:?xt=urn:btih:AD222466087EC7D65A961BB293CE476F936C69B5 111 | 名称: 战狼2.2017.bd1280高清中英双字-www.iidvd.com.mp4 112 | 大小: 1.1 GB 113 | 日期: 2018-02-21 114 | 热度: 29 115 | ``` 116 | 117 | **支持空格匹配多关键字** 118 | ``` 119 | $ torrent-cli 钢铁侠 3 120 | Crawling data for you..... 121 | 磁链: magnet:?xt=urn:btih:D43351FC74020C3E41F21C4E2D09736795D88DEE 122 | 名称: 钢铁侠3.iron.man.3.2013.bd1080p.x264.aac.mandarin&english.chs-eng.mp4ba 123 | 大小: 4.7 GB 124 | 日期: 2018-05-15 125 | 热度: 2 126 | 127 | 磁链: magnet:?xt=urn:btih:C65EBBB542C4D419AD4258530B1E80EF9A2AE105 128 | 名称: 钢铁侠3.mkv 129 | 大小: 1.7 GB 130 | 日期: 2018-03-09 131 | 热度: 1 132 | 133 | 磁链: magnet:?xt=urn:btih:8C00A1AEEFAFB69365784BD3CFA36C444585A4BF 134 | 名称: 钢铁侠3.iron.man.3.2013.bd1080p.x264.ac3.mandarin&english.chs-eng.adans 135 | 大小: 6.6 GB 136 | 日期: 2018-02-22 137 | 热度: 12 138 | 139 | 磁链: magnet:?xt=urn:btih:97BEF685F08F2CA98A6F11531CAE5DCD51EFD98B 140 | 名称: [www.hdmayi.com]钢铁侠3.2013.1080p.bd-mp4.国英双语.中英特效字幕 141 | 大小: 5.9 GB 142 | 日期: 2018-01-04 143 | 热度: 10 144 | 145 | 磁链: magnet:?xt=urn:btih:89244063F9B039F0587190BA46CA63B1D5C53361 146 | 名称: 2013.钢铁侠3.bd1080p英语中英双字[www.bdsee.cn].mp4 147 | 大小: 5.7 GB 148 | 日期: 2017-12-11 149 | 热度: 32 150 | 151 | 磁链: magnet:?xt=urn:btih:AFF3031AC9D8FD94FB8883E3CCB6FCE84CF68F0C 152 | 名称: 钢铁侠3【iron man3】【dvd-rmvb.英语中字】.rmvb 153 | 大小: 728.5 MB 154 | 日期: 2017-10-17 155 | 热度: 2 156 | 157 | 磁链: magnet:?xt=urn:btih:FD5C31C972723956811AA0F653A4C3205D5DBAEC 158 | 名称: 钢铁侠3.iron.man.3.2013.bd720p.x264.aac.mandarin&english.chs-eng.mp4ba 159 | 大小: 2.6 GB 160 | 日期: 2017-10-14 161 | 热度: 82 162 | 163 | 磁链: magnet:?xt=urn:btih:AA40AEC5F9481BB5F75833B7FCBE73A74D75266D 164 | 名称: 【钢铁侠3】【bluray-1080p高清-中英双字】【小罗伯特.唐尼2013科幻大片】 165 | 大小: 1.6 GB 166 | 日期: 2017-10-06 167 | 热度: 1 168 | 169 | 磁链: magnet:?xt=urn:btih:16BB0FBAC7BC9F40AE1522BA09820D3E60261664 170 | 名称: 钢铁侠3.iron.man.3.2013.bd1080p.超清中英字幕-minimp4 171 | 大小: 2.8 GB 172 | 日期: 2017-09-20 173 | 热度: 51 174 | 175 | 磁链: magnet:?xt=urn:btih:0F49B618CCAD8292EE1A3FC5E38F433D44C8C51C 176 | 名称: 钢铁侠3.iron.man.3.2013.bd1080p.x264.aac.mandarin&english.chs-eng.mp4ba.mp4 177 | 大小: 4.7 GB 178 | 日期: 2017-09-12 179 | 热度: 80 180 | ``` 181 | 182 | **单行显示并按大小排序(也可以指定排序顺序为 2,按热度排序)** 183 | ``` 184 | $ torrent-cli 战狼2 -p -s 1 185 | Crawling data for you..... 186 | magnet:?xt=urn:btih:CC3854CACBB5434E03EFF39C693B20223E0AA39D 56.8 GB 2018-05-14 187 | magnet:?xt=urn:btih:D6A5598C03C3123038DB6CAA04AE36D90BB569C6 35.0 GB 2018-02-22 188 | magnet:?xt=urn:btih:5B411E880CB585B5B596DBB25BB7F0927FD44F54 13.2 GB 2018-01-01 189 | magnet:?xt=urn:btih:B8E5C85B5B368060AB245AC5E434981B0D5543CA 12.4 GB 2018-02-23 190 | magnet:?xt=urn:btih:4640565A71BB840D6A082B7F8D387A5FF604941A 9.2 GB 2017-12-12 191 | magnet:?xt=urn:btih:B6401277BA77620727F7D6FE1345501555F7CA28 7.8 GB 2017-11-16 192 | magnet:?xt=urn:btih:2154B29E07DF4D21B67488C55667B1AB22CD63F4 7.8 GB 2017-12-17 193 | magnet:?xt=urn:btih:C1F01F089892ECF2AF168C190754B2921902D9E1 7.5 GB 2017-11-16 194 | magnet:?xt=urn:btih:DE42BC281CF39F0F489B64F06C2440466D545C83 5.4 GB 2017-12-13 195 | ``` 196 | 197 | **或者可以保存为 csv 或者 json 文件**(建议保存为 csv 文件,json 数据会被序列化,转为 utf 编码) 198 | ``` 199 | $ torrent-cli 战狼2 -o movie.csv 200 | ``` 201 | 202 | 203 | ### License 204 | 205 | MIT [©chenjiandongx](https://github.com/chenjiandongx) 206 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | beautifulsoup4 3 | lxml 4 | future 5 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal = 1 -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | author="chenjiandongx", 5 | author_email="chenjiandongx@qq.com", 6 | name="torrent-cli", 7 | version="0.0.9", 8 | license="MIT", 9 | url="https://github.com/chenjiandongx/torrent-cli", 10 | py_modules=["torrent"], 11 | install_requires=["bs4", "requests", "lxml", "future"], 12 | description="Magnets-Getter CLI Tools", 13 | entry_points={ 14 | "console_scripts": ["torrent-cli=torrent:command_line_runner"] 15 | }, 16 | ) 17 | -------------------------------------------------------------------------------- /torrent.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | from __future__ import division 4 | 5 | import os 6 | import re 7 | import csv 8 | import math 9 | import argparse 10 | import json 11 | import codecs 12 | 13 | import requests 14 | from bs4 import BeautifulSoup, Comment 15 | 16 | 17 | HEADERS = { 18 | 'X-Requested-With': 'XMLHttpRequest', 19 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 ' 20 | '(KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36' 21 | } 22 | 23 | VERSION = "VERSION 0.0.9" 24 | DOMAIN = "http://www.btyunsou.co" 25 | 26 | 27 | def get_parser(): 28 | """ 29 | 解析命令行参数 30 | """ 31 | parser = argparse.ArgumentParser(description='Magnets-Getter CLI Tools.') 32 | parser.add_argument('keyword', metavar="KEYWORD", type=str, nargs="*", 33 | help='magnet keyword.') 34 | parser.add_argument('-n', '--num', type=int, default=10, 35 | help='magnet number.(default 10)') 36 | parser.add_argument('-s', '--sort-by', type=int, default=0, 37 | help='0: Sort by date,1: Sort by size. 2: Sort by hot-rank.(default 0)') 38 | parser.add_argument('-o', '--output', type=str, 39 | help='output file path, supports csv and json format.') 40 | parser.add_argument('-p', '--pretty-oneline', action='store_true', 41 | help='show magnets info with one line.') 42 | parser.add_argument('-v', '--version', action='store_true', 43 | help='version information.') 44 | return parser 45 | 46 | 47 | def command_line_runner(): 48 | """ 49 | 执行命令行操作 50 | """ 51 | parser = get_parser() 52 | args = vars(parser.parse_args()) 53 | 54 | if args['version']: 55 | print(VERSION) 56 | return 57 | 58 | if not args["keyword"]: 59 | parser.print_help() 60 | else: 61 | magnets = run(kw=args["keyword"], 62 | num=args["num"], sort_by=args["sort_by"]) 63 | if args["output"]: 64 | _output(magnets, args["output"]) 65 | else: 66 | _print(magnets, args["pretty_oneline"]) 67 | 68 | 69 | def run(kw, num, sort_by): 70 | """ 71 | 爬虫入口 72 | 73 | :param kw: 资源名称 74 | :param num: 资源数量 75 | :param sort_by: 排序方式。0:按磁力时间排序,1:按文件大小排序 2:按磁力热度排序 76 | """ 77 | print("Crawling data for you.....") 78 | _kw = "%20".join(kw) 79 | # 排序类型选择 80 | if sort_by == 0: 81 | sort_str = "ctime" 82 | elif sort_by == 1: 83 | sort_str = "length" 84 | elif sort_by == 2: 85 | sort_str = "click" 86 | else: 87 | raise ValueError("Unknown Sort Method") 88 | 89 | # 确保 num 有效 90 | if num < 0 or num > 200: 91 | num = 10 92 | # 每页最多 10 条磁力信息 93 | page = int(math.ceil(num / 10)) 94 | magnets = [] 95 | for p in range(1, page + 1): 96 | url = DOMAIN + "/search/{kw}_{s}_{p}.html".format(kw=_kw, s=sort_str, p=p) 97 | try: 98 | resp = requests.get(url, headers=HEADERS).text.encode("utf-8") 99 | try: 100 | bs = BeautifulSoup(resp, "lxml").find( 101 | 'ul', class_='media-list media-list-set').find_all('li') 102 | if not bs: 103 | print("Sorry, found nothing :(") 104 | return 105 | for b in bs: 106 | _name = b.find( 107 | class_='media-body').find('h4').find( 108 | 'a', class_='title').get_text(strip=True) 109 | # 资源名称判断 110 | is_name_found= False 111 | name = _name.lower() 112 | for n in kw: 113 | if n.lower() in name: 114 | is_name_found = True 115 | if is_name_found: 116 | item = b.find('div', class_='media-more') 117 | time = item.find(class_='label label-success').text 118 | size = item.find(class_='label label-warning').text 119 | rank = item.find(class_='label label-primary').text 120 | link = re.findall( 121 | r'href="(.*?)">', 122 | str(item.find(text=lambda text: isinstance(text, Comment))))[0] 123 | magnets.append({ 124 | "magnet": link, # 磁力链接 125 | "magnet_name": name, # 磁力名称 126 | "magnet_date": time, # 磁力日期 127 | "magnet_size": size, # 磁力大小 128 | "magnet_rank": int(rank) # 磁力热度 129 | }) 130 | except: 131 | pass 132 | except Exception as e: 133 | print(e) 134 | return sort_magnets(magnets, sort_by, num) 135 | 136 | 137 | def sort_magnets(magnets, sort_by, num): 138 | """ 139 | 排序磁力 140 | 141 | :param magnets: 磁力列表 142 | :param sort_by: 排序方式 143 | """ 144 | # 按日期排序,默认 145 | if sort_by == 0: 146 | _magnets = sorted(magnets, 147 | key=lambda x: x["magnet_date"], 148 | reverse=True) 149 | # 按大小排序,统一单位为 kb 150 | elif sort_by == 1: 151 | for m in magnets: 152 | unit = m["magnet_size"].split() 153 | if unit[1] == "GB": 154 | _size = float(unit[0]) * 1024 * 1024 155 | elif unit[1] == "MB": 156 | _size = float(unit[0]) * 1024 157 | else: 158 | _size = float(unit[0]) 159 | m["magnet_size_kb"] = _size 160 | _magnets = sorted(magnets, 161 | key=lambda x: x["magnet_size_kb"], 162 | reverse=True) 163 | else: 164 | _magnets = sorted(magnets, 165 | key=lambda x: x["magnet_rank"], 166 | reverse=True) 167 | return _magnets[:num] 168 | 169 | 170 | def _print(magnets, is_show_magnet_only): 171 | """ 172 | 在终端界面输出结果 173 | 174 | :param magnets: 磁力列表 175 | :param is_show_magnet_only: 单行输出 176 | """ 177 | if not magnets: 178 | return 179 | if is_show_magnet_only: 180 | for row in magnets: 181 | print(row["magnet"], row["magnet_size"], row["magnet_date"]) 182 | else: 183 | for row in magnets: 184 | try: 185 | print("磁链:", row["magnet"]) 186 | print("名称:", row["magnet_name"]) 187 | print("大小:", row["magnet_size"]) 188 | print("日期:", row["magnet_date"]) 189 | print("热度:", row["magnet_rank"], "\n") 190 | except: 191 | print("磁链:", row["magnet"]) 192 | print("名称:", row["magnet_name"].encode('utf-8')) 193 | print("大小:", row["magnet_size"]) 194 | print("日期:", row["magnet_date"]) 195 | print("热度:", row["magnet_rank"], "\n") 196 | 197 | 198 | def _output(magnets, path): 199 | """ 200 | 将数据保存到本地文件 201 | 202 | :param magnets: 磁力列表 203 | :param path: 文件路径,支持 csv 和 json 两种文件格式 204 | """ 205 | if path: 206 | _, extension = os.path.splitext(path) 207 | if extension == ".csv": 208 | # 不兼容 Python2 209 | with open(path, mode="w+", encoding="utf-8-sig", newline="") as fout: 210 | fieldnames = ( 211 | "magnet", 212 | "magnet_name", 213 | "magnet_size", 214 | "magnet_date", 215 | "magnet_rank" 216 | ) 217 | f_csv = csv.DictWriter(fout, fieldnames, extrasaction="ignore") 218 | f_csv.writeheader() 219 | f_csv.writerows(magnets) 220 | print("Save successfully!") 221 | elif extension == ".json": 222 | with codecs.open(path, mode="w+", encoding="utf-8") as f: 223 | json.dump(magnets, f, indent=2) 224 | print("Save successfully!") 225 | else: 226 | print("Failed to save the file!") 227 | 228 | 229 | if __name__ == "__main__": 230 | command_line_runner() 231 | --------------------------------------------------------------------------------