├── .gitignore ├── build.py ├── config.json ├── config.py ├── crawler.py ├── crawler_test.py ├── main.py ├── main.qml ├── readme.md ├── requirements.txt ├── resource.py ├── resource.qrc ├── rule ├── _temp.json ├── bak │ ├── btsearch.json │ └── cili9.json ├── bitsearch.json ├── bt113.json ├── btbtbt.json ├── btgg.json ├── bthook.json ├── bthub.json ├── btsow.json ├── btsow_proxy.json ├── cili.json ├── cursor.json ├── sofan.json ├── zhongziso.json └── zooqle.json ├── toolchain ├── navigation.txt ├── update_rule.py ├── website.txt └── website_update.py └── user_agent.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | 3 | build 4 | log 5 | venv 6 | -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | 4 | 5 | def build_dev(): 6 | # 执行打包 7 | os.system('pyinstaller --upx-dir build/ -y --specpath build --distpath build/debug/ --workpath build/cache/ main.py') 8 | 9 | # 拷贝规则文件 10 | shutil.copytree('rule/', 'build/debug/main/rule', dirs_exist_ok = True) 11 | 12 | # 拷贝配置文件 13 | shutil.copytree('config/', 'build/debug/main/config', dirs_exist_ok = True) 14 | 15 | 16 | def build_prod(): 17 | # 使用resource.qrc方式加载 18 | os.system('pyside6-rcc resource.qrc -o resource.py') 19 | # 替换main.py的内容 20 | main_info = open('main.py', 'r+', encoding = 'utf-8') 21 | infos = main_info.readlines() 22 | main_info.seek(0, 0) 23 | for line in infos: 24 | line_new = line.replace("engine.load('main.qml')", "engine.load('qrc:/main.qml')") 25 | main_info.write(line_new) 26 | main_info.close() 27 | 28 | # 执行打包 29 | os.system('pyinstaller --noconsole --upx-dir build/ -y --specpath build --distpath build/release/ --workpath build/cache/ main.py') 30 | 31 | # 拷贝规则文件 32 | shutil.copytree('rule/', 'build/release/main/rule', dirs_exist_ok = True) 33 | 34 | # 拷贝配置文件 35 | shutil.copy2('config.json', 'build/release/main/') 36 | 37 | 38 | if __name__ == '__main__': 39 | # pip install nuitka 40 | # nuitka --mingw64 --standalone --follow-imports --enable-plugin=pyside6 --include-qt-plugins=all --output-dir=build main.py 41 | # pip install pyinstaller 42 | build_prod() 43 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxy": { 3 | "enable": false, 4 | "type": "http", 5 | "host": "localhost", 6 | "port": 9910, 7 | "username": "", 8 | "password": "" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | class Config: 5 | def __init__(self): 6 | with open('config.json', 'r') as c: 7 | self._config = json.load(c) 8 | 9 | def save_config(self, config): 10 | print(config) 11 | self._config = config 12 | 13 | with open('config/proxy.json', 'r') as c: 14 | config = json.dumps(config, ensure_ascii = False, indent = 2, separators = (', ', ': ')) 15 | c.write(config) 16 | 17 | def get_config(self): 18 | return self._config 19 | -------------------------------------------------------------------------------- /crawler.py: -------------------------------------------------------------------------------- 1 | import json 2 | import re 3 | import sys 4 | from urllib import parse 5 | 6 | from html5lib import HTMLParser, treebuilders 7 | from loguru import logger 8 | from lxml import etree 9 | from requests import get 10 | 11 | from user_agent import random_ua 12 | 13 | magnet_head = 'magnet:?xt=urn:btih:' 14 | 15 | 16 | def run_crawler(key: str, search_terms: str, page: int, sort: str, proxies): 17 | rule_name = f'rule/{key}.json' 18 | logger.info('搜索任务开始执行') 19 | logger.info(f'文件名称: {rule_name}, 搜索词: {search_terms}, 页数: {page}, 排序规则: {sort}') 20 | 21 | try: 22 | with open(rule_name, encoding = 'utf-8') as rule_json: 23 | rule = json.load(rule_json) 24 | 25 | # 排序条件 26 | # TODO: 各个网站规则不一,暂不实现 27 | if len(sort) == 0: 28 | path = rule['path']['default'].format(k = search_terms, p = page) 29 | else: 30 | path = '' 31 | page_url = rule['url'] + path 32 | logger.info(f'搜索网址: {page_url}') 33 | 34 | # 发送请求获取数据 35 | headers = { 36 | 'referer': parse.quote(rule['referer']), 37 | 'user-agent': random_ua() 38 | } 39 | content = get(page_url, timeout = 10, headers = headers, proxies = proxies) 40 | parser = HTMLParser(treebuilders.getTreeBuilder('lxml'), namespaceHTMLElements = False) 41 | document = parser.parse(content.text) 42 | 43 | # 获取页数 44 | page_sel = rule['parse']['page'] 45 | page_num = '' 46 | for sel in page_sel: 47 | if sel['type'] is None: 48 | page_num = '0' 49 | break 50 | elif sel['type'] == 'xpath': 51 | page_elem = document.xpath(sel['xpath']) 52 | if len(page_elem) == 0: 53 | page_num = '0' 54 | else: 55 | page_num = page_elem[0] 56 | elif sel['type'] == 'regex': 57 | page_num = re.findall(sel['regex'], page_num) 58 | if len(page_num) == 0: 59 | page_num = '0' 60 | else: 61 | page_num = page_num[0] 62 | page_num = int(page_num) 63 | 64 | # 获取数据列表(字符串格式) 65 | data_result = [] 66 | item_list = [] 67 | if rule['parse']['item']["type"] == "xpath": 68 | elem_list = document.xpath(rule['parse']['item']['xpath']) 69 | for elem in elem_list: 70 | item_list.append(etree.tostring(elem, encoding = str)) 71 | elif rule['parse']['item']["type"] == "url": 72 | item_urls = document.xpath(rule['parse']['item']['xpath']) 73 | start = 0 74 | end = len(item_urls) 75 | if page_num == 0: 76 | page_num = int(len(item_urls) / 10) 77 | if page <= page_num: 78 | start = (page - 1) * 10 79 | end = start + 10 80 | for index in range(start, end): 81 | url = rule['url'] + item_urls[index] 82 | item_content = get(url, timeout = 10, headers = headers, proxies = proxies) 83 | item_list.append(item_content.text) 84 | logger.info(f'结果列表: {item_list}') 85 | 86 | # 解析数据列表 87 | for index in range(rule['parse']['item']['startIndex'], len(item_list)): 88 | # 按照规则解析数据 89 | item_data = { 90 | 'magnet': 'magnet', 91 | 'name': 'name', 92 | 'hot': 'hot', 93 | 'size': 'size', 94 | 'time': 'time', 95 | } 96 | for key in item_data: 97 | value = '' 98 | 99 | # 遍历规则处理数据 100 | for sel in rule['parse'][item_data[key]]: 101 | # xpath匹配规则 102 | if sel['type'] == 'xpath': 103 | value = etree.HTML(item_list[index]).xpath(sel['xpath']) 104 | # xpath匹配结果都是列表 105 | if len(value) == 0: 106 | value = '' 107 | else: 108 | value = value[0] 109 | 110 | # xpath列表匹配规则 111 | if sel['type'] == 'xpathList': 112 | values = etree.HTML(item_list[index]).xpath(sel['xpath']) 113 | # xpath匹配结果是列表 114 | if len(values) == 0: 115 | value = '' 116 | else: 117 | value = '' 118 | for text in values: 119 | value += text 120 | 121 | # 字符串截取规则 122 | elif sel['type'] == 'subIndex': 123 | # 起始和结束不设置时 124 | # 需要为null值 125 | start = 0 if sel['start'] is None else sel['start'] 126 | end = len(value) if sel['end'] is None else sel['end'] 127 | value = value[start:end] 128 | 129 | # 正则表达式匹配规则 130 | elif sel['type'] == 'regex': 131 | value = re.findall(sel['regex'], value) 132 | # 正则匹配结果是列表 133 | if len(value) == 0: 134 | value = '' 135 | else: 136 | value = value[0] 137 | 138 | # 没有规则,取默认值 139 | elif sel['type'] is None: 140 | value = sel['default'] 141 | break 142 | 143 | # fix: 某些链接提取后不完整 144 | if key == 'magnet' and magnet_head not in value: 145 | value = magnet_head + value 146 | 147 | # fix: 移除一些错误字符 148 | if key == 'name': 149 | #   150 | value = value.replace(u'\xa0', u'') 151 | 152 | # 保存解析后数据 153 | item_data[key] = value 154 | 155 | data_result.append(item_data) 156 | except Exception as e: 157 | # 监听到异常 158 | logger.error(f'出现异常, {e.with_traceback(sys.exc_info()[2])}') 159 | return None 160 | else: 161 | # 没有异常返回正确数据 162 | logger.success(f'解析后结果列表: {data_result}') 163 | return { 164 | "page": page_num, 165 | "list": data_result 166 | } 167 | finally: 168 | # 有无异常都会最终执行的操作 169 | logger.info('搜索任务执行完毕') 170 | -------------------------------------------------------------------------------- /crawler_test.py: -------------------------------------------------------------------------------- 1 | import json 2 | from urllib import parse 3 | 4 | from html5lib import HTMLParser, treebuilders 5 | from lxml import etree 6 | from requests import get 7 | 8 | from crawler import run_crawler 9 | from user_agent import random_ua 10 | 11 | key = 'btsearch' 12 | search_terms = '龙珠' 13 | page = 1 14 | sort = '' 15 | 16 | proxies = {'http': 'http://127.0.0.1:9910', 'https': 'http://127.0.0.1:9910', } 17 | 18 | 19 | def test_request(): 20 | headers = { 21 | 'user-agent': random_ua() 22 | } 23 | 24 | # 发送请求获取数据 25 | # https://bot.sannysoft.com/ 26 | # https://httpbin.org/headers 27 | content = get("https://bot.sannysoft.com/", timeout = 10, headers = headers) 28 | print(content.text) 29 | 30 | 31 | def test_crawler(): 32 | data = run_crawler(key, search_terms, page, sort, proxies) 33 | print(len(data)) 34 | for d in data: 35 | print(d) 36 | 37 | 38 | def test_9cili(): 39 | rule_name = f'rule/{key}.json' 40 | with open(rule_name, encoding = 'utf-8') as rule_json: 41 | rule = json.load(rule_json) 42 | page_url = rule['url'] + rule['path']['default'].format(k = search_terms, p = page) 43 | headers = { 44 | 'referer': parse.quote(rule['referer']), 45 | 'user-agent': random_ua() 46 | } 47 | content = get(page_url, timeout = 10, headers = headers) 48 | 49 | parser = HTMLParser(treebuilders.getTreeBuilder('lxml'), namespaceHTMLElements = False) 50 | 51 | doc = parser.parse(content.text) 52 | print(etree.tostring(doc, encoding = str)) 53 | 54 | elem_list = doc.xpath('//div[@class="search_list"]/dl') 55 | for elem in elem_list: 56 | print(etree.tostring(elem, encoding = str)) 57 | 58 | 59 | def test_btsearch(): 60 | pass 61 | 62 | 63 | if __name__ == '__main__': 64 | # test_request() 65 | # test_9cili() 66 | test_crawler() 67 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import io 3 | import json 4 | import os 5 | import re 6 | import sys 7 | from concurrent.futures import ThreadPoolExecutor 8 | 9 | from PySide6.QtCore import QAbstractListModel, Qt, QModelIndex, QObject, Slot, Property, Signal 10 | from PySide6.QtGui import QGuiApplication 11 | from PySide6.QtQml import QQmlApplicationEngine 12 | from loguru import logger 13 | from qrcode import QRCode 14 | from requests import head 15 | 16 | from config import Config 17 | from crawler import run_crawler 18 | from resource import qInitResources 19 | 20 | 21 | class QDataListModel(QAbstractListModel): 22 | NAME = Qt.UserRole + 1000 23 | TIME = Qt.UserRole + 1001 24 | SIZE = Qt.UserRole + 1002 25 | HOT = Qt.UserRole + 1003 26 | MAGNET = Qt.UserRole + 1004 27 | 28 | def __init__(self, model): 29 | QAbstractListModel.__init__(self) 30 | self.model = model 31 | 32 | def rowCount(self, parent = None) -> int: 33 | return len(self.model) 34 | 35 | def roleNames(self): 36 | return { 37 | self.NAME: b'name', 38 | self.TIME: b'time', 39 | self.SIZE: b'size', 40 | self.HOT: b'hot', 41 | self.MAGNET: b'magnet', 42 | } 43 | 44 | def data(self, index: QModelIndex, role: int = None): 45 | index = index.row() 46 | row = self.model[index] 47 | 48 | return row[str(self.roleNames()[role], 'utf-8')] 49 | 50 | 51 | class MainWindow(QObject): 52 | def __init__(self, app: QGuiApplication, config: Config): 53 | QObject.__init__(self) 54 | self._app = app 55 | self._config = config 56 | self._pool = ThreadPoolExecutor() 57 | self._search_result_model = QDataListModel([]) 58 | 59 | @Slot(result = 'QVariant') 60 | def get_rules(self): 61 | pro_list = ['bitsearch', 'btsow_proxy', 'zooqle'] 62 | rules = [] 63 | 64 | file_list = os.listdir('rule') 65 | for file in file_list: 66 | if file == '_temp.json' or file == 'bak': 67 | continue 68 | with open('rule/' + file, encoding = 'utf-8') as f: 69 | rule_obj = json.load(f) 70 | rules.append({ 71 | 'pro': rule_obj['id'] in pro_list, 72 | 'key': rule_obj['id'], 73 | 'value': rule_obj['name'] 74 | }) 75 | rules.sort(key = lambda x: x['value'], reverse = False) 76 | return rules 77 | 78 | @Slot(result = 'QVariant') 79 | def get_config(self): 80 | return self._config.get_config() 81 | 82 | @Slot(str, int, result = str) 83 | def test_proxy(self, server, port): 84 | logger.info(f'检查代理是否符合规则: {server}:{port}') 85 | # 校验代理地址 86 | server_reg = re.compile(r'^((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}') 87 | if server != 'localhost' and server_reg.match(server) is None: 88 | logger.error(f'代理校验失败, 代理地址不符合规则') 89 | return 'failed' 90 | # 校验代理端口号 91 | if port == 0: 92 | logger.error(f'代理校验失败, 代理端口不符合规则') 93 | return 'failed' 94 | 95 | logger.info(f'检查代理是否可用: {server}:{port}') 96 | proxies = {'http': f'http://{server}:{port}', 'https': f'http://{server}:{port}'} 97 | try: 98 | r = head('https://www.google.com/', proxies = proxies, timeout = 5) 99 | if r.status_code == 200: 100 | logger.success('代理校验成功') 101 | return 'success' 102 | else: 103 | logger.error('代理校验失败') 104 | return 'failed' 105 | except Exception as e: 106 | logger.error(f'代理校验失败: {e}') 107 | return 'failed' 108 | 109 | @Slot(str, result = str) 110 | def magnet_qr_code(self, magnet): 111 | logger.info(f'生成二维码: {magnet}') 112 | qr = QRCode() 113 | qr.make(fit = True) 114 | qr.add_data(magnet) 115 | qr_img = qr.make_image() 116 | 117 | buf = io.BytesIO() 118 | qr_img.save(buf, format = 'PNG') 119 | image_stream = buf.getvalue() 120 | buf.close() 121 | return f'data:image/png;base64,{base64.b64encode(image_stream).decode()}' 122 | 123 | @Slot(str) 124 | def download(self, magnet): 125 | print('调用迅雷下载') 126 | # os.system(f'"D:/apps/Thunder/Program/ThunderStart.exe" {magnet}') 127 | print(magnet) 128 | 129 | @Slot(str) 130 | def copy_to_clipboard(self, magnet): 131 | logger.info(f'复制内容: {magnet} 到剪切板') 132 | cb = self._app.clipboard() 133 | cb.setText(magnet) 134 | 135 | def search_done(self, future): 136 | if future.result() is None: 137 | # 通知页面数据加载失败(忽视编辑器莫名其妙的警告) 138 | # noinspection PyUnresolvedReferences 139 | self.loadStateChanged.emit('error', 0) 140 | else: 141 | result = future.result() 142 | self._search_result_model = QDataListModel(result["list"]) 143 | # 通知页面数据加载完成(忽视编辑器莫名其妙的警告) 144 | # noinspection PyUnresolvedReferences 145 | self.loadStateChanged.emit('loaded', result["page"]) 146 | 147 | @Slot(str, str, int) 148 | def search(self, key, search_terms, page): 149 | logger.info(f'提交搜索任务, 网站规则: {key}, 搜索词: {search_terms}, 页数: {page}') 150 | # 提交任务 151 | proxy_config = self._config.get_config()["proxy"] 152 | proxies = {} 153 | if proxy_config["enable"]: 154 | proxies = { 155 | 'http': f'{proxy_config["type"]}://{proxy_config["host"]}:{proxy_config["port"]}', 156 | 'https': f'{proxy_config["type"]}://{proxy_config["host"]}:{proxy_config["port"]}' 157 | } 158 | self._pool.submit(run_crawler, key, search_terms, page, '', proxies).add_done_callback(self.search_done) 159 | # 通知页面处于加载状态(忽视编辑器莫名其妙的警告) 160 | # noinspection PyUnresolvedReferences 161 | self.loadStateChanged.emit('loading', 0) 162 | 163 | loadStateChanged = Signal(str, int) 164 | 165 | # 绑定QML数据 166 | @Property(QObject, constant = False, notify = loadStateChanged) 167 | def search_result_model(self): 168 | return self._search_result_model 169 | 170 | 171 | def main(): 172 | logger.remove(handler_id = None) 173 | logger.add(sys.stdout) 174 | logger.add(sink = 'log/magnet.log', rotation = '100 MB', retention = '30 days', 175 | enqueue = True, compression = 'zip', level = 'DEBUG', encoding = 'utf-8', 176 | format = '{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {file}:{line} | {name}:{function} | {message}') 177 | 178 | app = QGuiApplication(sys.argv) 179 | engine = QQmlApplicationEngine() 180 | 181 | # 初始化资源 182 | qInitResources() 183 | 184 | # 绑定视图 185 | backend = MainWindow(app, Config()) 186 | engine.rootContext().setContextProperty('backend', backend) 187 | engine.load('qrc:/main.qml') 188 | 189 | if not engine.rootObjects(): 190 | return -1 191 | 192 | return app.exec() 193 | 194 | 195 | if __name__ == '__main__': 196 | sys.exit(main()) 197 | -------------------------------------------------------------------------------- /main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 6 2 | import QtQuick.Window 6 3 | import QtQuick.Controls 6 4 | import QtQuick.Layouts 6 5 | import QtQuick.Controls.Material 6 6 | 7 | ApplicationWindow { 8 | id: main 9 | title: "磁力链接搜索" 10 | width: 1280 11 | height: 720 12 | minimumWidth: 960 13 | minimumHeight: 540 14 | visible: true 15 | visibility: Window.Windowed 16 | 17 | Material.theme: Material.Dark 18 | 19 | Connections { 20 | target : backend 21 | function onLoadStateChanged(state, page_num) { 22 | switch(state) { 23 | case "error": 24 | search.text = "搜索" 25 | search.enabled = true 26 | message_info.text = "加载错误,请稍后重试" 27 | message_timer.start() 28 | break 29 | case "loading": 30 | search.text = "正在搜索" 31 | search.enabled = false 32 | page_up.enabled = false 33 | page_down.enabled = false 34 | break 35 | case "loaded": 36 | search.text = "搜索" 37 | search.enabled = true 38 | page_up.enabled = page > 1 39 | page_down.enabled = page < page_num 40 | break 41 | } 42 | } 43 | } 44 | 45 | Component.onCompleted: { 46 | var rules_data = backend.get_rules() 47 | for (var i = 0; i < rules_data.length; i++) { 48 | rules_model.append({ 49 | 'key': rules_data[i]['key'], 50 | 'value': rules_data[i]['value'], 51 | }) 52 | if (rules_data[i]['pro']) { 53 | rules_pro_model.append({ 54 | 'key': rules_data[i]['key'], 55 | 'value': rules_data[i]['value'], 56 | }) 57 | } 58 | } 59 | rules.currentIndex = 0 60 | 61 | var config = backend.get_config() 62 | proxy_enable.checked = config["proxy"]["enable"] 63 | if (config["proxy"]["type"] === "http") { 64 | proxy_type_http.checked = true 65 | } else if (config["proxy"]["type"] === "socks5") { 66 | proxy_type_socks5.checked = true 67 | } 68 | proxy_host.text = config["proxy"]["host"] 69 | proxy_port.text = config["proxy"]["port"] 70 | proxy_username.text = config["proxy"]["username"] 71 | proxy_password.text = config["proxy"]["password"] 72 | } 73 | 74 | Popup { 75 | id: qr_code_popup 76 | anchors.centerIn: parent 77 | width: 360 78 | height: 360 79 | Image { 80 | id: qr_code 81 | anchors.fill: parent 82 | } 83 | } 84 | 85 | Popup { 86 | id: message_popup 87 | x: (main.width-width)/2 88 | y: 0 89 | width: 200 90 | height: 36 91 | enter: Transition { 92 | PropertyAnimation { 93 | property: "y" 94 | to: 36 95 | duration: 200 96 | } 97 | } 98 | exit: Transition { 99 | PropertyAnimation { 100 | property: "y" 101 | to: 0 102 | duration: 200 103 | } 104 | } 105 | Label { 106 | id: message_info 107 | anchors.centerIn: parent 108 | font.pointSize: 10 109 | text: "消息提示" 110 | } 111 | } 112 | 113 | Timer { 114 | id: message_timer 115 | interval: 1000 116 | repeat: true 117 | triggeredOnStart: true 118 | property int message_show: 3 119 | onTriggered: { 120 | if (message_show == 3) { 121 | message_popup.open() 122 | } 123 | message_show -= 1 124 | if (message_show == 0) { 125 | message_show = 3 126 | message_timer.stop() 127 | message_popup.close() 128 | } 129 | } 130 | } 131 | 132 | ApplicationWindow { 133 | id: setting_window 134 | title: "设置" 135 | width: 600 136 | height: 480 137 | minimumWidth: 600 138 | minimumHeight: 480 139 | maximumWidth: 600 140 | maximumHeight: 480 141 | flags: Qt.Dialog 142 | modality: Qt.WindowModal 143 | 144 | Material.theme: Material.Dark 145 | visible: false 146 | 147 | ColumnLayout { 148 | anchors.fill: parent 149 | anchors.margins: 20 150 | focus: true 151 | RowLayout { 152 | Layout.fillHeight: true 153 | Layout.fillWidth: true 154 | ListModel { 155 | id: setting_menu_list 156 | ListElement { 157 | name: "搜索设置" 158 | } 159 | ListElement { 160 | name: "代理设置" 161 | } 162 | ListElement { 163 | name: "缓存设置" 164 | } 165 | } 166 | Component { 167 | id: setting_menu_item 168 | ItemDelegate { 169 | width: parent.width 170 | height: 36 171 | highlighted: ListView.isCurrentItem 172 | 173 | RowLayout { 174 | anchors.fill: parent 175 | Layout.fillHeight: true 176 | Layout.fillWidth: true 177 | Layout.alignment: Qt.AlignCenter | Qt.AlignVCenter 178 | 179 | Label { 180 | text: model.name 181 | Layout.leftMargin: 8 182 | Layout.rightMargin: 8 183 | Layout.fillWidth: true 184 | } 185 | } 186 | 187 | onClicked: { 188 | setting_menu.currentIndex = index 189 | setting_menu_content.currentIndex = index 190 | } 191 | } 192 | } 193 | 194 | ListView { 195 | id: setting_menu 196 | Layout.minimumWidth: 120 197 | Layout.fillHeight: true 198 | spacing: 8 199 | 200 | model: setting_menu_list 201 | delegate: setting_menu_item 202 | } 203 | ToolSeparator { 204 | bottomPadding: -52 205 | topPadding: 0 206 | Layout.fillHeight: true 207 | } 208 | StackLayout { 209 | id: setting_menu_content 210 | currentIndex: 0 211 | Layout.minimumWidth: 400 212 | Layout.fillHeight: true 213 | Layout.fillWidth: true 214 | Item { 215 | Label { 216 | text: "搜索设置" 217 | } 218 | } 219 | Item { 220 | Layout.fillHeight: true 221 | Layout.fillWidth: true 222 | 223 | GridLayout { 224 | rowSpacing: 16 225 | columnSpacing: 20 226 | anchors { 227 | top: parent.top 228 | left: parent.left 229 | right: parent.right 230 | rightMargin: 36 231 | } 232 | columns: 2 233 | 234 | Label { text: "启用代理" } 235 | Switch { 236 | id: proxy_enable 237 | text: checked ? "是" : "否" 238 | hoverEnabled: false 239 | } 240 | 241 | Label { text: "代理类型" } 242 | RowLayout { 243 | width: 100 244 | height: 100 245 | RadioButton { 246 | id: proxy_type_http 247 | text: "HTTP" 248 | hoverEnabled: false 249 | } 250 | RadioButton { 251 | id: proxy_type_socks5 252 | text: "SOCKS5" 253 | hoverEnabled: false 254 | } 255 | } 256 | 257 | Label { text: "代理地址" } 258 | TextField { 259 | id: proxy_host 260 | Layout.fillWidth: true 261 | hoverEnabled: false 262 | selectByMouse: true 263 | } 264 | 265 | Label { text: "代理端口" } 266 | TextField { 267 | id: proxy_port 268 | Layout.fillWidth: true 269 | hoverEnabled: false 270 | selectByMouse: true 271 | validator: IntValidator { bottom: 0; top: 65535 } 272 | } 273 | 274 | Label { text: "代理账号" } 275 | TextField { 276 | id: proxy_username 277 | Layout.fillWidth: true 278 | hoverEnabled: false 279 | selectByMouse: true 280 | } 281 | 282 | Label { text: "代理密码" } 283 | TextField { 284 | id: proxy_password 285 | Layout.fillWidth: true 286 | hoverEnabled: false 287 | selectByMouse: true 288 | echoMode: TextInput.Password 289 | } 290 | } 291 | } 292 | Item { 293 | Label { 294 | text: "缓存设置" 295 | } 296 | } 297 | } 298 | } 299 | RowLayout { 300 | Layout.fillWidth: true 301 | Layout.fillHeight: true 302 | Layout.alignment: Qt.AlignRight | Qt.AlignTop 303 | Button { 304 | text: "确定" 305 | onClicked: { 306 | console.log("保存") 307 | } 308 | } 309 | Button { 310 | text: "取消" 311 | onClicked: close() 312 | } 313 | } 314 | } 315 | } 316 | 317 | menuBar: MenuBar { 318 | Menu { 319 | title: "磁力链接搜索" 320 | MenuItem { 321 | text: "搜索设置" 322 | onTriggered: { 323 | setting_window.visible = true 324 | } 325 | } 326 | MenuItem { 327 | id: list_pro_ctrl 328 | text: "只加载优质规则" 329 | onTriggered: { 330 | switch(text) { 331 | case "只加载优质规则": 332 | rules.model = rules_pro_model 333 | list_pro_ctrl.text = "加载全部规则" 334 | break 335 | case "加载全部规则": 336 | rules.model = rules_model 337 | list_pro_ctrl.text = "只加载优质规则" 338 | break 339 | } 340 | } 341 | } 342 | MenuItem { 343 | text: "退出" 344 | onTriggered: Qt.quit() 345 | } 346 | } 347 | Menu { 348 | title: "扩展功能" 349 | MenuItem { 350 | text: "网盘搜索" 351 | onTriggered: { 352 | console.log("网盘搜索") 353 | } 354 | } 355 | MenuItem { 356 | text: "视频下载" 357 | onTriggered: { 358 | console.log("视频下载") 359 | } 360 | } 361 | } 362 | Menu { 363 | title: "帮助" 364 | MenuItem { 365 | text: "使用手册" 366 | onTriggered: console.log("打开网页") 367 | } 368 | MenuItem { 369 | text: "关于" 370 | onTriggered: console.log("检查更新等") 371 | } 372 | } 373 | } 374 | 375 | ListModel { id: rules_pro_model } 376 | ListModel { id: rules_model } 377 | 378 | property int page: 1 379 | Item { 380 | id: search_info 381 | height: 80 382 | ComboBox { 383 | id: rules 384 | x: 36 385 | y: 20 386 | width: 180 387 | model: rules_model 388 | textRole: "value" 389 | valueRole: "key" 390 | } 391 | TextField { 392 | id: search_terms 393 | text: "龙珠" 394 | width: 480 395 | anchors { 396 | top: rules.top 397 | left: rules.right 398 | leftMargin: 20 399 | } 400 | hoverEnabled: false 401 | selectByMouse: true 402 | placeholderText: "搜索词" 403 | font.pointSize: 12 404 | } 405 | Button { 406 | id: search 407 | width: 80 408 | anchors { 409 | top: search_terms.top 410 | left: search_terms.right 411 | leftMargin: 20 412 | } 413 | text: "搜索" 414 | onClicked: { 415 | backend.search(rules.currentValue, search_terms.text, page) 416 | } 417 | } 418 | Button { 419 | id: page_up 420 | width: 40 421 | anchors { 422 | top: search_terms.top 423 | left: search.right 424 | leftMargin: 20 425 | } 426 | text: "▲" 427 | enabled: false 428 | onClicked: { 429 | if (page === 1) { 430 | return 431 | } 432 | page -= 1 433 | backend.search(rules.currentValue, search_terms.text, page) 434 | } 435 | } 436 | Button { 437 | id: page_down 438 | width: 40 439 | anchors { 440 | top: search_terms.top 441 | left: page_up.right 442 | leftMargin: 10 443 | } 444 | text: "▼" 445 | enabled: false 446 | onClicked: { 447 | page += 1 448 | backend.search(rules.currentValue, search_terms.text, page) 449 | } 450 | } 451 | } 452 | 453 | ListView { 454 | id: search_result 455 | anchors { 456 | top: search_info.bottom 457 | right: parent.right 458 | bottom: parent.bottom 459 | left: parent.left 460 | topMargin: 20 461 | rightMargin: 36 462 | bottomMargin: 20 463 | leftMargin: 36 464 | } 465 | spacing: 20 466 | clip: true 467 | ScrollBar.vertical: ScrollBar {} 468 | boundsBehavior: Flickable.StopAtBounds 469 | 470 | model: backend.search_result_model 471 | 472 | delegate: Item { 473 | width: main.width - 80 474 | height: 80 475 | Column { 476 | id: info 477 | anchors { 478 | left: parent.left 479 | right: handler.left 480 | verticalCenter: parent.verticalCenter 481 | } 482 | Label { 483 | anchors { 484 | left: parent.left 485 | right: parent.right 486 | rightMargin: 16 487 | } 488 | text: model.name 489 | font.pixelSize: 16 490 | bottomPadding: 20 491 | clip: true 492 | } 493 | Row { 494 | spacing: 20 495 | Label { 496 | text: "热度: " + model.hot 497 | color: "gray" 498 | font.pixelSize: 12 499 | } 500 | Label { 501 | text: "文件大小: " + model.size 502 | color: "gray" 503 | font.pixelSize: 12 504 | } 505 | Label { 506 | text: "创建时间: " + model.time 507 | color: "gray" 508 | font.pixelSize: 12 509 | } 510 | } 511 | } 512 | 513 | Row { 514 | id: handler 515 | anchors { 516 | right: parent.right 517 | rightMargin: 20 518 | verticalCenter: parent.verticalCenter 519 | } 520 | spacing: 20 521 | Button { 522 | id: qrcode 523 | height: 40 524 | text: "二维码" 525 | onClicked: { 526 | qr_code.source = backend.magnet_qr_code(model.magnet) 527 | qr_code_popup.open() 528 | } 529 | } 530 | Button { 531 | id: download 532 | height: 40 533 | text: "迅雷下载" 534 | onClicked: { 535 | backend.download(model.magnet) 536 | } 537 | } 538 | Button { 539 | id: copy_url 540 | height: 40 541 | text: "复制链接" 542 | onClicked: { 543 | backend.copy_to_clipboard(model.magnet) 544 | message_info.text = "复制成功" 545 | message_timer.start() 546 | } 547 | } 548 | } 549 | } 550 | } 551 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ### 效果展示 2 | 3 | ![image](https://user-images.githubusercontent.com/20694755/126852020-52fedd53-6fb8-4e7d-b9a7-ad40ce71066f.png) 4 | 5 | 6 | ### 全部组件 7 | [QT官网](https://doc.qt.io/qt-6/qmltypes.html) 8 | 9 | 10 | https://github.com/leovan/SciHubEVA 11 | 12 | https://www.coder.work/article/6332330 13 | 14 | https://blog.csdn.net/Likianta/article/details/105820227 15 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | PySide6~=6.1.2 2 | requests~=2.26.0 3 | lxml~=4.6.3 4 | qrcode~=7.2 5 | loguru~=0.5.3 6 | Pillow~=8.3.1 7 | html5lib~=1.1 -------------------------------------------------------------------------------- /resource.py: -------------------------------------------------------------------------------- 1 | # Resource object code (Python 3) 2 | # Created by: object code 3 | # Created by: The Resource Compiler for Qt version 6.1.2 4 | # WARNING! All changes made in this file will be lost! 5 | 6 | from PySide6 import QtCore 7 | 8 | qt_resource_data = b"\ 9 | \x00\x00\x0c\x9a\ 10 | \x00\ 11 | \x00D\x8bx\x9c\xd5\x1cko\x1c\xb7\xf1{\x80\xfc\x87\ 12 | \xc5}\xb1\x02\xc7W\xbf\xe4\xba\xd7\xb8\x85\xa5$\x8d\xd1\ 13 | \x18q,\xc1\xf9`\x18\xc2j\x97\xba[hoy\xd9\ 14 | \xe5YRS\x016\xdc\xf8m\xcbA\x12\xc7\xa9\x93\xe6\ 15 | \xe1<\x9c\x16\xb6\x92\xc6u\x02?\xffK\xa1\xbd\x93>\ 16 | \xf5/\x94\xb3\x5c\xdeq\xb9\xe4.W\x96lx>\xd8\ 17 | \xb7\xe4\x0c\xc9\x19\xce\x0c\x87\xe4P^\xbb\x83Cb\xbd\ 18 | M\xde\xeez\xce\xac\xb5\xe7\xc5\x17\xbcLI\xfd\x1d/\ 19 | p\xf1\x9c\xa2b\x1c\x07$\xc4~\xa4\xa8z\xd3^\xc0\ 20 | ]\xa2\xaa\xe1D\xf5\x836A\xa1g\xfb\x80\xf3\xe2\x0b\ 21 | \xfb;\x1d\xdfsl\xe2\xe1 \xed\xef\xbd\x17_\xb0(\ 22 | xn\xc3j\xdb^\xc0\xbe\x88G|\xd4\xb0j\xfd\x1b\ 23 | '\xe3\xf3\xd7\xd7>|\xd4\xbb\xfcm\xef\xcag\xfd;\ 24 | _\xd7\x18\xc2\x9c\xe7\x92V\xc3\xda\xb1s\xefvV\xd0\ 25 | B^\xb3E\x1a\xd6ow\xa6\x05m/\xf0\xda\xdd\xf6\ 26 | ;\x0c\xf1w{\xb2\xc5o\xa4\xe8\xa3\xbb\xd3\xf2\xe3^\ 27 | \xe4MC\x9f$\xec\x22\xa1\xc8\xf3=\xb2\xd0\xb0\xd8`\ 28 | S\x19!\x17X\x01\x14\xce\x5c\x9d\xb4P\x9b\x12\x0f\xbe\ 29 | _\xb5\xc3Y\x8eDE\x11 \x07X\x8e8\xb7\x09\x8f\ 30 | v\xd8D\xc4jX\xd3\xb63\x8b\x02wX3\xd3\x0d\ 31 | \x12t\x0b\x07ob\xdb\x9d \xb4\xd5\xf1\x96\x1d4\x91\ 32 | ;\x12\xc1\xc7\xcbV\xc7n\xa2\xa9\xa0\xdb~Il\x11\ 33 | \x9a\xf3\x88\xd3bh\xb9J\x00\xc7\x8e\x90UCa\ 34 | \x88\xc3Z#_\x9d\xb4\x81\xec\xd0i\xd5\x09\x9a'\xd6\ 35 | >\xab\x96\x11\xbc\x06\x17\x056\x95\x9eK\xd1\x87\xf2\x93\ 36 | \xa1\x8d\xa2\x08\x86\xed\x053x\xd0x|\xfe\xcb\xd5\x87\ 37 | \x0f\xd7>\xfatuy\xf9\x7f\x0f.\xae.\xff\xd2\xbf\ 38 | y)\xbery\xed\xcc\xa5\xd5\xe5\x8f5\x9d\xf2\x96\x88\ 39 | \xd7Fa\x9d\xf2\x1a\x92\x91\x97\xd4\xa8\xd3!\xb2gu\ 40 | R\xf0\xa9t\xbd\xa0i*\x87[7\xe2\xcfnV\x93\ 41 | \xc6\x8c\xedG\x1aq$S\xd8\xedT@\xa6\xaa\x17\x98\ 42 | \xa1\x97r\x8d\xdc\xa7<\xf9yn\xa1\xc4\xfa\x83\xb5\xc3\ 43 | \x9c\xe1\x84\xe2\x95\x81\xee\x1b\xb3\xbe8\xfcL\x7f.\x0e\ 44 | m\x93\xba\xad\x00\x05\xa4\x8e\x03\xf8\xed#\x82\xa8'\x12\ 45 | \xec\xe6\xb8\x1dZa\xd7G\xd1\x94k\x13\x9b\x8e\x225\ 46 | \xd7:5\xde\xa9\xa4BT\xbd\x19\x1cZ#@\xe2Q\ 47 | \xcc\xed\xbf\xa7\xff\xbd\x22P\xd7}\x144I\x8b\x16o\ 48 | \xdd\x9a3N\x86\xd6\xc6.\xf2\xebv\xa7C\xbb\x18Q\ 49 | \x98\xef\x96Y\xb4\xb0\xa5!\xb4y\xd4;v4)<\ 50 | \xf6\xb2\x02\xfb\xb8\xedwQ\x1e\x9f\x15\xcb\x14\x8b\x92\x0d\ 51 | y3\xd6\x88D\xd8\x09\xf1\x96cJ\xbf\xc2\x10i}\ 52 | )\x0b\xd5\xd9\xa8\xce\x8a\x8a\x9d\xbc\x1a\x0c\xc6]w\xba\ 53 | aH\xb5\xe0@\xe0\xa2y\x989\xae\x1f\x000\x9d\x0e\ 54 | \x0ef\xbc\xa64\xfb\xacP\x9c~\xca\xfe\xfc\xc2\x14\xd3\ 55 | \xd8\xba\xd3B\x14\x17\x14\x97!\x1e\xad%\xd5\xb5cG\ 56 | k\x0c\xa3vlH\x09\xb2\xce\xa1\x91\x85\x0eE\xb2\xf6\ 57 | \xed\xa3\x86\xd8\x22\xa4S\xcbI\x9eu\x08xS\x80 \ 58 | \xf4\x995\xc5E\x0bQgQ\xdeK\x84\x9d\xd9h\xb4\ 59 | \xb0\x1f\x86\xa2\xefI\x96F\x0bG\x84\xbb\x93\x5c\xdfP\ 60 | )\x8a\x81\x91@$\xa1%\x81\xca\x8eP\x01\x0b\ 83 | \xf2,k\xb7\x82\x093T\xb2\x11\x22\x84F\xe7Ss\ 84 | I\xad0\x89\xe9\xe6p\xf5\xf6\xa3\xfe\xc3\xdb\x82\x1e\xa5\ 85 | \x0ef\x8f\xca\xc1\xec\xde+\x14f\xf7\x86\x19|i\x7f\ 86 | \x98%\xb3\xe7\xb5d\xacJI6\xe3\xdb\xcd\xa8Aw\ 87 | \xc6\xf5W\xe9\xd6\x107\x05*\xec\xdal\x7fI+\x99\ 88 | \x10\x0eB\x91\x18}\x94l19\xda`\xff\x9a\xee\x0a\ 89 | \x865\xe3\xd8\xef\xb6\x03\xb6S\x97\xb5\xa1xm\x101\ 90 | \xdat\xb7\xea\x05\x11\xb8\x1a\xd9\xf4\x9dn$\xdb\x11\xc0\ 91 | a<\xa7\xee\x14\x80\xd5$\xfdr\x99\xa9\xf7\x0e\x02b\ 92 | *w\x0d\x9e\x17\x91\x83\x10x\xaaz\x03\x105\xaa\x8d\ 93 | \x82\xee\x94O)\xd4\xa8\xd0\xd6k>\x95v\xa0\x1c;\ 94 | \x07\x88&\x1a|\x87\x94SF\x11\x167\xa2\x9f\x95\xfb\ 95 | 7\xfaWNo~?\xfd\x07\x1f\xc6\xb7\xaeU\xedG\ 96 | Q4\xd8[\x19O\x89G\x90fWw\x80\xd6\xbc\x8a\ 97 | |\xd4\xa4\xda_\xc4C\xea\x02\x98&\xb3\xb8D\x8f\xac\ 98 | \x0a>r8\x14\xc5\x074\xf0\xf5 \xc8#\x1e\x9a\xab\ 99 | {\xd1x\xbaaHF\xac'/4\x02\x11\xca-Q\ 100 | \x06c\x13\xd2\x10\x15\x9a\x93\x82\x86z\xaaf\x00:\x94\ 101 | x\xab\xfd\xf05\x9e\x04\x05\xd6_\x07\x05GXI\x91\ 102 | DX\x8b\x8a8D\x05,n`\x1bJP\xcfr\x8a\ 103 | t\xb0>\x9a!\x07\x13\x97\xd5\xb0\xf6\x1aS\x85 \xc6\ 104 | \xead\x95\xa4\xa9\xb1\xd1\xb4J_\x89\x83q\xba\x5c\xce\ 105 | *B\x0e\x19D\x93\x927\xb6\x1e\xfcoN\x0e[\x5c\ 106 | \x02\x96T\xad\x19\x0d\x8fj\xb7\xa1\xf6\xe5`f\xa6~\ 107 | C\xe3\xf5\xd8\xe4d\xd7\xfa\x1d\xf2\xf2%a\x9bYS\ 108 | \xd4\xb1\x1d\xday\xa2#j\x8cDe\x8d\x17\x1c7\xf5\ 109 | lF\xeeP!\xc5I\x8c\xfd\x09D\x9d\x86Mp\xa8\ 110 | \x93\xda4&\x04\xb7\x0f\xd9\xae\x9b\x0c}\xdb\xe8N5\ 111 | \x1e\x0d\xf6\x06HO*,\xc5Xi\xdc\xed\xcc\x16\xfb\ 112 | \xc4\xdc\xba\x90j\xa1\x1a[T\xcd\xb2\x11g\x95a\xb7\ 113 | \xbck\xaa\xcc\x9f\x84\x5c\xea\x04`\xb9(2_#\xc7\ 114 | \xc87S\xe5q\x07\x80\xb9-\x9a\x0d\xb0\xe2\xa2\xa3\x93\ 115 | \x8e\x9e\xe2O\xa1\xe7\x9a\xad\x99!\x9e\x9b\xe0\x96\xb8\xa3\ 116 | `\x0d\x07p\x92(x\x80\xaes\x03\x1c\xd2\xe5\xd8h\ 117 | \x8d\xc2\x9dA\xc0A\x7f\x97\x13\xc0\xda4\xa0\x80\x8fr\ 118 | \x92\x90\x89:\xa5I\xbe\x0c\x89\xf8jV\x14\xe3\x00\x14\ 119 | ,K\x00L|\x10\xfe\x1b\xae\xed\x5cK\xe3+\xcb\xfd\ 120 | \x8fn\xb2\xd8\xb5V\xd6\xcbDrye\x22tp\x11\ 121 | \xe2a\xabi(\xc1O-\xffH\xed\xe7\xdar\xcdJ\ 122 | F\xf8]\x81\xf9ph\xe1\xe3(|\x8d]E4\x8a\ 123 | \xae^8\x14.\xe6\x00\x92\xa0\x98\x88\xfa?\xdd\x8f\xff\ 124 | q\xa1TP\xc6a%\x00\xbf+\xd5y;\x11xH\ 125 | l\x84|\xd8v=<\xd6\xa5\xcb\x8a\xf2PK\x05\xc3\ 126 | y\x1b\x9cY\x9b\x11\xa6Rzcr\xf2\x90\xc1l\x01\ 127 | T\x9e1\x80\x12\xb9\x03<9\xd7\xec\x04\xbd\x12\xdf\x13\ 128 | o\x8d\xffyb\xf4\x19r\xbe>u\x8e?\xfb1\xfe\ 129 | \xfcD\xa9:OR\x9a\xd7=\xe4\xbb\xd5L\x1f.\x0f\ 130 | 6'H\x07X\x97\x14#\x1a\xc99dl\xe1 \xee\ 131 | F\xc8p;\xb0\x1e7\xf1\xaf\xe5x\xe9\xc6f\xc9\x15\ 132 | nX\x9ew\xb9\x02\x1c\xa7[V\x17B\xe2\x86u \ 133 | G\xf8\x17\x15&\x8b\x85\x1bpC\x9b,\xdf{F\ 134 | Gw\x8dn\x8e\x09\xac\xde\xf9.^\xfae\xb3\xa6\x8a\ 135 | \xdfj=\xef\xd3\xb5N\xf7\xb2|\xba\xff\xe5\xc9M3\ 136 | \x83\xf4\xda\xefy\x97-\x00\xa2\xe1,\x1c\x8f6\x12a\ 137 | \x1c\x08:t\xb8\x87\x8c\xf8+>\xaf\xa8P\xbc\x91{\ 138 | \x1f\x833\xcaj\x03\x94\x8a\xa4O\xd3\xa3\xec\xe2\x13\xea\ 139 | \x8aG\xde\x8a\xf3\xb6\xc3@&\x1c\xb7M\xaa\xb6\x1b\xc5\ 140 | \xa1\x09\x17\xe0W\xb7\xe3\xdb\x7f\xd7\x88\xce\xec\xa8\x89n\ 141 | \xca#\xec\xa3\xba\x8f\x9b#\xb5\x95\xc7\x9f\xd3\x09\xa9i\ 142 | \x92\xb0\xcc\xce\x8b\x8d\x06\x1e/]\xed\xdd=[>p\ 143 | \xe5m\x94\xa2\xe3\x82\x0b*8z\x18\xb3\xe9\xe2q\x90\ 144 | \xfd\x10G\x06E\xf2HK\x93\x16Eb\x9d5\x98m\ 145 | \xee\x8bn 9d\xaf\xcf\xea\xe9\x05\x916I\xab\xd8\ 146 | \x02\x8a\x86\x0c\x1e\x13\xce\xb6\x92\xe4\x1f\x87\x84\xbe\x96\xab\ 147 | x\xe9\x9f,\xdfo\xe5\xc1\xb5\xd5;7W\xbf\xff[\ 148 | |\xf6\xd3\xf5\xb2\xc7\x12\x1d\xa1e\xe5%'\x07\x96\xf3\ 149 | \xa6\xeeY\x93\x02\xc7\x81\xa5\x06%GyTlR\x82\ 150 | S1iF\x1eR\xb2c\xfc\xfe\xcd\xb5Sz\xe6E\ 151 | \xd0\xe4\xf1I\xbc\xe5[]\x07c\xebg\xcapR\x0d\ 152 | \xf9\xaa\xec\x9c\x0d\xaci\xed\xc4\x89\xf8\xcc\xbd2E\xa3\ 153 | ^\xf5\xdd\xae\x97\xcb$U\xa7R\x149\x80\xde\xb9\x1f\ 154 | \xe2\x9f>\x8e\xcf\x7f\xb1z\xeaau\xd3\xef?\xfc\xa0\ 155 | \x7f\xfd\x9a6\xef\xd2\xc462\xae9\xd3^%\x87h\ 156 | 8\xe0\xd5\xefO\xaf}\xfd\xc1\xca\xaf\x17\xa8\x0el\xc4\ 157 | \x803\xed\xad\xc7\x83\xf3q\xeb\xe6'\xfe\xf5v|\xfe\ 158 | \x87\xea3\xb3\xf2\xf0q\xff\xa3\x9b\xbds\x17\xe2\xd3\x17\ 159 | \xcb\x18\xcdp\xd4;\xf7a\xfc\xe0\x04\x9d\x88\xb5\xaf\xfe\ 160 | #sT]\xde\xf1\xfb?\xaf\xdc\xbb\x5cm\x007N\ 161 | \xf4\xbe\xf8\xb6w\xfdN\xef\xea\x8f\xfd[\xe7\x0a\xc6 \ 162 | /\x82\xc2\xbdz\xe2\xe8%/\xc8\xf1\xd5h\x03\x14\x86\ 163 | \x94\xc9\xae\x81,\xde\x06\xcfa\x919f7\x00\x90\x5c\ 164 | ,\xa5$\xf1\xf3)1\xbfb\x1c\xb7\xa7\xf1\x18\x9eW\ 165 | %6%\xe3\xc8\x16\xcf\xe7\x0fC\x17\xf2\x07\xc2\xfc\xd0\ 166 | l\xafT\x9e^\xech}&\xcc\xd1a\x9c\xa8Y\x92\ 167 | \x99*MSR\x96\xd6\xcf\xa2\x85|\x12\x14\x80v\xbf\ 168 | \x22\x88\x85\xa0\xb0\x1d\xe5\xbb\x06g\xf7\xe8\xd3\xfe\xd2\x97\ 169 | 5%;\xbbev\x0a\xce\xb9\x93\x8d1[)\x94\xc7\ 170 | \xda\xec\x18\x9b!hN\xa4\xc5[XY\xc0\x92\xde\x97\ 171 | n\x85J\xb7=\x1d\xdfvP\x0b\xfb.\x0a'3A\ 172 | \xd4\xf2%I\x18\xb9l\xb5\x9d\xcaiP\xc7\xa3\xc39\ 173 | PJ\xb8\xaa\x80\xc5\xe9,\x92s\x06\xef\xc9\xc5\x9d\x09\ 174 | 3%\xf1\x14\x87\xff<\x01\x9a\x0dh$\x93>}\x04\ 175 | \xb4\xfbe\x89'\xda\x13{\xafb\xb4\xae\xea\x85\x9e\xbe\ 176 | P\xeb\xf5\xa6J}\xe3\xe4\xfd\xdf\xab\xff\x96\x84\x8d\ 177 | \x0aT\xbex\x22 \xdf/y\x11\x01\x89\xdb;\xb41\ 178 | p\x88H7\x0c\x8c6`Ik\xf9\xc4B\x80g;\ 179 | \xeb\xf0\x0e\xe4\xa9\xce;\x7f\xadb0\xf1r\xaa\xabn\ 180 | \xe2\x1fl\xd8\xc4'\xd3\xb4\xf5iOS&\x22\x90\xb3\ 181 | 3\x84\x85)DQ\xd7\x17d\xa6\x99\x12q:\x92\x07\ 182 | a\xecH6\x8bTz\xed\xc9\xcfqS\x0cU\x1b%\ 183 | \xb7\xadt\x1c:\x13.\xbc?e]\xe9HE\x05\x11\ 184 | )\x05\xb1F\xaa\xabh\xc7\xf7:\xf2\xda6\xe1\x84\xd8\ 185 | \xf7\xc7\xec\xb0NWH\xe29\x90\xeb<(\xb3\xde\x13\ 186 | \x9a\x9c\xc6\xdd\xc0\x8d\xc6P\xcb>\xee\xc1\xa1\xf7\xeb\xa0\ 187 | D\xc9S\x94\x09\xca\xe6~2\x96\xd4\x8b'\xadi4\ 188 | \x93U\x9bt\x0ayt3\xc4\x1e\xa6\xa9\xa8\x22\xd4\xd4\ 189 | $\x87\x0f\x02\xacm\xb9\xd5P\x15\xbe\x01\xb0\x1cU\xdd\ 190 | \xe1B>+\x1d\xa0\xe4\x8a\xde\xf0\x96=U\xb1\x96\x1d\ 191 | \xb8>\x0a\x0b\x10\xb9\xf0\xc7\xd3\xe7\x09i\xcb\xd9b#\ 192 | 7[x\xd0i\x90xP!\x7f\xa0R\xde@F\xdf\ 193 | u\xf9\x14\x9a#U\xb3D=\x16xy\xf3\xc8O\x03\ 194 | /M'R\xaa\x92.YCe-\x05\xe3<\x8c\xb5\ 195 | \x19eJc\x14\xa1\xf4p\x9ao\xdeO\xdd\x8a\xef}\ 196 | G\x7fX[Si\xb4p\x81\xc8\x1d\xec\x83\xa1\xd6\x9a\ 197 | \xa1\xadz\xf7\xc1!'7M\xea\x96.\xff\xd7p\xf0\ 198 | \xbd\xabgV\xee\xdf\x8d\xbf\xf9>\xfeqId!\xa2\ 199 | \x9d>/<\xc4g\xaf\xc7\xf7\xef\xf5>\xb9\xbb\xf6\xc9\ 200 | \x1d\x91\x07x\xc9\xf0,y\xc8\x1fZd\x0b4\xca\x09\ 201 | \xee/\xf5M\x95=\xa0\xb1\xf1g\x0c_g\x01\x1b\xe7\ 202 | \xff\x0a\x8d\xad\xf8\x12\x80=r\xcb\xbfq\xe30x\xed\ 203 | \xa1a\x82\x1f\xe4\xdc\xbb\xd8\xbf\x7f\x07\xae\x0e\xd5hf\ 204 | \x17 \xe9k\xbbz\x84\xbb\xa1\x83\x84\xb7\xa1m\xbb\x19\ 205 | 2\x95\xd6\x8f0\x05d\x85\x9a\x0b\x12\xa1\xb9\x82\xf7\ 206 | @\x1c6\xe2:\x05$\x09a5<\x06\x7f\x22Y\xae\ 207 | >~\x7f\xed\xfa/\xda\xd3?\x003qr\xe9\xf1Q\ 208 | \x99\xc8m\xa3$\xe1\xe0\xce\xc2TWus\x01`(\ 209 | \x89\xf8\x9bK\xf1\xd9\xbb\xec\xdegC$\x91\x8c\x8a\xe0\ 210 | )X\xe7\xa6\xb1\x1d\x1a\x89\x04@\xfd\x97\x16\x92\xe1\xf5\ 211 | \xce^\x89\xcf\x7fQ\xe0\xe3*\xfcm\x85JG\xf5\xc3\ 212 | m\xc4\xe2\xff\x01\x80\x11d\xe9\ 213 | " 214 | 215 | qt_resource_name = b"\ 216 | \x00\x08\ 217 | \x08\x01Z\x5c\ 218 | \x00m\ 219 | \x00a\x00i\x00n\x00.\x00q\x00m\x00l\ 220 | " 221 | 222 | qt_resource_struct = b"\ 223 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ 224 | \x00\x00\x00\x00\x00\x00\x00\x00\ 225 | \x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\ 226 | \x00\x00\x01{\x14\xff\xb4\xaa\ 227 | " 228 | 229 | def qInitResources(): 230 | QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) 231 | 232 | def qCleanupResources(): 233 | QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) 234 | 235 | qInitResources() 236 | -------------------------------------------------------------------------------- /resource.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | 5 | 6 | -------------------------------------------------------------------------------- /rule/_temp.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "", 3 | "name": "", 4 | "desc": "", 5 | "proxy": false, 6 | "publish": "", 7 | "publishMail": "", 8 | "url": "", 9 | "referer": "", 10 | "path": { 11 | "default": "" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "", 16 | "xpath": "", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": null, 22 | "default": 0 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "", 28 | "default": "" 29 | } 30 | ], 31 | "name": [ 32 | { 33 | "type": "", 34 | "default": "" 35 | } 36 | ], 37 | "hot": [ 38 | { 39 | "type": "", 40 | "default": "" 41 | } 42 | ], 43 | "size": [ 44 | { 45 | "type": "", 46 | "default": "" 47 | } 48 | ], 49 | "time": [ 50 | { 51 | "type": "", 52 | "default": "" 53 | } 54 | ] 55 | } 56 | } -------------------------------------------------------------------------------- /rule/bak/btsearch.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "btsearch", 3 | "name": "磁力社区【慢】", 4 | "desc": "【未完成】", 5 | "proxy": false, 6 | "publish": "", 7 | "publishMail": "admin@btsearch.cc", 8 | "url": "https://www.btsearch.cc", 9 | "referer": "https://www.btsearch.cc", 10 | "path": { 11 | "default": "/{k}/?c=&s=time&p={p}" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "url", 16 | "xpath": "//ul[@class='mlist']/li/h3/a/@href", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": "xpath", 22 | "xpath": "//ul[@class='pg']/a[last()-1]/text()" 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "xpath", 28 | "xpath": "//dl[@class='BotInfo']/p[6]/a/text()" 29 | } 30 | ], 31 | "name": [ 32 | { 33 | "type": "xpath", 34 | "xpath": "//div[@class='main']/h1/text()" 35 | } 36 | ], 37 | "hot": [ 38 | { 39 | "type": "xpath", 40 | "xpath": "//dl[@class='BotInfo']/p[4]/text()" 41 | }, 42 | { 43 | "type": "subIndex", 44 | "start": 6, 45 | "end": null 46 | } 47 | ], 48 | "size": [ 49 | { 50 | "type": "xpath", 51 | "xpath": "//dl[@class='BotInfo']/p[3]/text()" 52 | }, 53 | { 54 | "type": "subIndex", 55 | "start": 6, 56 | "end": null 57 | } 58 | ], 59 | "time": [ 60 | { 61 | "type": "xpath", 62 | "xpath": "//dl[@class='BotInfo']/p[1]/text()" 63 | }, 64 | { 65 | "type": "subIndex", 66 | "start": 6, 67 | "end": null 68 | } 69 | ] 70 | } 71 | } -------------------------------------------------------------------------------- /rule/bak/cili9.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "cili9", 3 | "name": "磁力海", 4 | "desc": "", 5 | "proxy": false, 6 | "publish": "https://9cili.com", 7 | "publishMail": "", 8 | "url": "https://drxdsn0k.xyz", 9 | "referer": "https://drxdsn0k.xyz", 10 | "path": { 11 | "default": "/search-{k}-0-0-{p}.html" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='search_list']/dl[@class='detail']", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": "xpath", 22 | "xpath": "//div[@class='pagediv']/span[1]/text()" 23 | }, 24 | { 25 | "type": "regex", 26 | "regex": "共([\\d.]+)页" 27 | } 28 | ], 29 | "magnet": [ 30 | { 31 | "type": "xpath", 32 | "xpath": "//dd[@class='info']/span/a/@href" 33 | } 34 | ], 35 | "name": [ 36 | { 37 | "type": "xpathList", 38 | "xpath": "//dt/a/span//text()" 39 | } 40 | ], 41 | "hot": [ 42 | { 43 | "type": "xpath", 44 | "xpath": "//dd[@class='info']/span[5]/b/text()" 45 | } 46 | ], 47 | "size": [ 48 | { 49 | "type": "xpath", 50 | "xpath": "//dd[@class='info']/span[3]/text()" 51 | }, 52 | { 53 | "type": "regex", 54 | "regex": "文档大小:([\\d.]+\\s[A-Z].)" 55 | } 56 | ], 57 | "time": [ 58 | { 59 | "type": "xpath", 60 | "xpath": "//dd[@class='info']/span[1]/b/text()" 61 | } 62 | ] 63 | } 64 | } -------------------------------------------------------------------------------- /rule/bitsearch.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "bitsearch", 3 | "name": "BitSearch", 4 | "desc": "【优】【英文】【支持中文搜索】", 5 | "proxy": false, 6 | "publish": "", 7 | "publishMail": "", 8 | "url": "https://bitsearch.to", 9 | "referer": "https://bitsearch.to", 10 | "path": { 11 | "default": "/search?q={k}&page={p}" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='search-result view-box']", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": "xpath", 22 | "xpath": "//div[@class='pagination text-right']/a[last()-1]/text()" 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "xpath", 28 | "xpath": "//div[contains(@class,'links')]/a[2]/@href" 29 | } 30 | ], 31 | "name": [ 32 | { 33 | "type": "xpath", 34 | "xpath": "//h5[contains(@class,'title')]/a/text()" 35 | } 36 | ], 37 | "hot": [ 38 | { 39 | "type": "xpath", 40 | "xpath": "//div[@class='stats']/div[3]/font/text()" 41 | } 42 | ], 43 | "size": [ 44 | { 45 | "type": "xpath", 46 | "xpath": "//div[@class='stats']/div[2]/text()" 47 | } 48 | ], 49 | "time": [ 50 | { 51 | "type": "xpath", 52 | "xpath": "//div[@class='stats']/div[last()]/text()" 53 | } 54 | ] 55 | } 56 | } -------------------------------------------------------------------------------- /rule/bt113.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "bt113", 3 | "name": "磁力多", 4 | "desc": "", 5 | "proxy": false, 6 | "publish": "https://bt113.com", 7 | "publishMail": "", 8 | "url": "https://duo1.dns33.top:39988", 9 | "referer": "https://duo1.dns33.top:39988/?host=duo22.buzz", 10 | "path": { 11 | "default": "/search-{k}-rel-{p}.html" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='p-wrapper']/div[5]/div[@class='ssbox']", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": null, 22 | "default": 0 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "xpath", 28 | "xpath": "//div[@class='sbar']//a/@href" 29 | } 30 | ], 31 | "name": [ 32 | { 33 | "type": "xpathList", 34 | "xpath": "//h3/a//text()" 35 | } 36 | ], 37 | "hot": [ 38 | { 39 | "type": "xpath", 40 | "xpath": "//div[@class='sbar']/span[5]/b/text()" 41 | } 42 | ], 43 | "size": [ 44 | { 45 | "type": "xpath", 46 | "xpath": "//div[@class='sbar']/span[3]/b/text()" 47 | } 48 | ], 49 | "time": [ 50 | { 51 | "type": "xpath", 52 | "xpath": "//div[@class='sbar']/span[2]/b/text()" 53 | } 54 | ] 55 | } 56 | } -------------------------------------------------------------------------------- /rule/btbtbt.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "btbtbt", 3 | "name": "种子搜索", 4 | "desc": "", 5 | "proxy": false, 6 | "publish": "https://xn--i8sq8r6zst7c.com/", 7 | "publishMail": "52btbtbt@gmail.com", 8 | "url": "https://cl.clcl108.com", 9 | "referer": "https://cl.clcl108.com", 10 | "path": { 11 | "default": "/search-{k}-0-0-{p}.html" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='tbox']/div[@class='ssbox']", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": "xpath", 22 | "xpath": "//div[@class='pager']/span[1]/text()" 23 | }, 24 | { 25 | "type": "regex", 26 | "regex": "共([\\d.]+)页" 27 | } 28 | ], 29 | "magnet": [ 30 | { 31 | "type": "xpath", 32 | "xpath": "//div[@class='sbar']/span[1]/a/@href" 33 | } 34 | ], 35 | "name": [ 36 | { 37 | "type": "xpathList", 38 | "xpath": "//div[@class='title']/h3/a//text()" 39 | } 40 | ], 41 | "hot": [ 42 | { 43 | "type": "xpath", 44 | "xpath": "//div[@class='sbar']/span[5]/b/text()" 45 | } 46 | ], 47 | "size": [ 48 | { 49 | "type": "xpath", 50 | "xpath": "//div[@class='sbar']/span[3]/b/text()" 51 | } 52 | ], 53 | "time": [ 54 | { 55 | "type": "xpath", 56 | "xpath": "//div[@class='sbar']/span[2]/b/text()" 57 | } 58 | ] 59 | } 60 | } -------------------------------------------------------------------------------- /rule/btgg.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "btgg", 3 | "name": "BTGG【代理】", 4 | "desc": "", 5 | "proxy": true, 6 | "publish": "", 7 | "publishMail": "", 8 | "url": "https://www.btgg.cc", 9 | "referer": "https://www.btgg.cc", 10 | "path": { 11 | "default": "/search?q={k}&p={p}" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='list']/div[@class='item']", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": null, 22 | "default": 0 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "xpath", 28 | "xpath": "//div[@class='meta']/a/@href" 29 | } 30 | ], 31 | "name": [ 32 | { 33 | "type": "xpath", 34 | "xpath": "//div[@class='name']/a/text()" 35 | } 36 | ], 37 | "hot": [ 38 | { 39 | "type": null, 40 | "default": 99 41 | } 42 | ], 43 | "size": [ 44 | { 45 | "type": "xpath", 46 | "xpath": "//div[@class='meta']/span[1]/text()" 47 | }, 48 | { 49 | "type": "subIndex", 50 | "start": 0, 51 | "end": -2 52 | } 53 | ], 54 | "time": [ 55 | { 56 | "type": "xpath", 57 | "xpath": "//div[@class='meta']/span[3]/text()" 58 | }, 59 | { 60 | "type": "subIndex", 61 | "start": 0, 62 | "end": -2 63 | } 64 | ] 65 | } 66 | } -------------------------------------------------------------------------------- /rule/bthook.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "bthook", 3 | "name": "磁力树", 4 | "desc": "和cili9的规则一致", 5 | "proxy": false, 6 | "publish": "bthook.cc", 7 | "publishMail": "", 8 | "url": "https://4raq0y70.xyz", 9 | "referer": "https://4raq0y70.xyz", 10 | "path": { 11 | "default": "/search-{k}-0-0-{p}.html" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='search_list']/dl[@class='detail']", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": "xpath", 22 | "xpath": "//div[@class='pagediv']/span[1]/text()" 23 | }, 24 | { 25 | "type": "regex", 26 | "regex": "共([\\d.]+)页" 27 | } 28 | ], 29 | "magnet": [ 30 | { 31 | "type": "xpath", 32 | "xpath": "//dd[@class='info']/span/a/@href" 33 | } 34 | ], 35 | "name": [ 36 | { 37 | "type": "xpathList", 38 | "xpath": "//dt/a/span//text()" 39 | } 40 | ], 41 | "hot": [ 42 | { 43 | "type": "xpath", 44 | "xpath": "//dd[@class='info']/span[5]/b/text()" 45 | } 46 | ], 47 | "size": [ 48 | { 49 | "type": "xpath", 50 | "xpath": "//dd[@class='info']/span[3]/text()" 51 | }, 52 | { 53 | "type": "regex", 54 | "regex": "文档大小:([\\d.]+\\s[A-Z].)" 55 | } 56 | ], 57 | "time": [ 58 | { 59 | "type": "xpath", 60 | "xpath": "//dd[@class='info']/span[1]/b/text()" 61 | } 62 | ] 63 | } 64 | } -------------------------------------------------------------------------------- /rule/bthub.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "bthub", 3 | "name": "BTHUB", 4 | "desc": "", 5 | "proxy": false, 6 | "publish": "https://github.com/fwonggh/Bthub", 7 | "publishMail": "", 8 | "url": "https://bthub.xyz/cn", 9 | "referer": "https://bthub.xyz/cn", 10 | "path": { 11 | "default": "/search/kw-{k}-{p}.html" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='search-item detail-width']", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": "xpath", 22 | "xpath": "//div[@class='bottom-pager detail-width']/a[last()-1]/text()" 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "xpath", 28 | "xpath": "//div[@class='item-title']/h3/a/@href" 29 | }, 30 | { 31 | "type": "subIndex", 32 | "start": -45, 33 | "end": -5 34 | } 35 | ], 36 | "name": [ 37 | { 38 | "type": "xpath", 39 | "xpath": "//div[@class='item-title']/h3/a/@title" 40 | } 41 | ], 42 | "hot": [ 43 | { 44 | "type": "xpath", 45 | "xpath": "//div[@class='item-bar']/span[3]/b/text()" 46 | } 47 | ], 48 | "size": [ 49 | { 50 | "type": "xpath", 51 | "xpath": "//div[@class='item-bar']/span[1]/b/text()" 52 | } 53 | ], 54 | "time": [ 55 | { 56 | "type": "xpath", 57 | "xpath": "//div[@class='item-bar']/span[2]/b/text()" 58 | } 59 | ] 60 | } 61 | } -------------------------------------------------------------------------------- /rule/btsow.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "btsow", 3 | "name": "BTSOW", 4 | "desc": "【优】", 5 | "proxy": false, 6 | "publish": "https://btsow.com", 7 | "publishMail": "", 8 | "url": "https://btsow.one", 9 | "referer": "https://btsow.one", 10 | "path": { 11 | "default": "/search/{k}/page/{p}" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='data-list']/div[@class='row']", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": "xpath", 22 | "xpath": "//ul[contains(@class,'pagination')]/li[last()-1]/a/text()" 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "xpath", 28 | "xpath": "//a/@href" 29 | }, 30 | { 31 | "type": "subIndex", 32 | "start": -40, 33 | "end": null 34 | } 35 | ], 36 | "name": [ 37 | { 38 | "type": "xpath", 39 | "xpath": "//a/@title" 40 | } 41 | ], 42 | "hot": [ 43 | { 44 | "type": null, 45 | "default": 99 46 | } 47 | ], 48 | "size": [ 49 | { 50 | "type": "xpath", 51 | "xpath": "//div[contains(@class,'text-right size')]/text()" 52 | } 53 | ], 54 | "time": [ 55 | { 56 | "type": "xpath", 57 | "xpath": "//div[contains(@class,'text-right date')]/text()" 58 | } 59 | ] 60 | } 61 | } -------------------------------------------------------------------------------- /rule/btsow_proxy.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "btsow_proxy", 3 | "name": "BTSOW【代理】", 4 | "desc": "【优】", 5 | "proxy": true, 6 | "publish": "https://btsow.com", 7 | "publishMail": "", 8 | "url": "https://btsow.com", 9 | "referer": "https://btsow.com", 10 | "path": { 11 | "default": "/search/{k}/page/{p}" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='data-list']/div[@class='row']", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": "xpath", 22 | "xpath": "//ul[contains(@class,'pagination')]/li[last()-1]/a/text()" 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "xpath", 28 | "xpath": "//a/@href" 29 | }, 30 | { 31 | "type": "subIndex", 32 | "start": -40, 33 | "end": null 34 | } 35 | ], 36 | "name": [ 37 | { 38 | "type": "xpath", 39 | "xpath": "//a/@title" 40 | } 41 | ], 42 | "hot": [ 43 | { 44 | "type": null, 45 | "default": 99 46 | } 47 | ], 48 | "size": [ 49 | { 50 | "type": "xpath", 51 | "xpath": "//div[contains(@class,'text-right size')]/text()" 52 | } 53 | ], 54 | "time": [ 55 | { 56 | "type": "xpath", 57 | "xpath": "//div[contains(@class,'text-right date')]/text()" 58 | } 59 | ] 60 | } 61 | } -------------------------------------------------------------------------------- /rule/cili.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "cili", 3 | "name": "无极磁链【慢】", 4 | "desc": "", 5 | "proxy": false, 6 | "publish": "https://cili.st", 7 | "url": "https://6mag.net", 8 | "referer": "https://6mag.net", 9 | "path": { 10 | "default": "/search?q={k}" 11 | }, 12 | "parse": { 13 | "item": { 14 | "type": "url", 15 | "xpath": "//table[contains(@class,'file-list')]//td/a/@href", 16 | "startIndex": 0 17 | }, 18 | "page": [ 19 | { 20 | "type": null, 21 | "default": 0 22 | } 23 | ], 24 | "magnet": [ 25 | { 26 | "type": "xpath", 27 | "xpath": "//input[@id='input-magnet']/@value" 28 | } 29 | ], 30 | "name": [ 31 | { 32 | "type": "xpath", 33 | "xpath": "//h2[@class='magnet-title']/text()" 34 | } 35 | ], 36 | "hot": [ 37 | { 38 | "type": null, 39 | "default": 99 40 | } 41 | ], 42 | "size": [ 43 | { 44 | "type": "xpath", 45 | "xpath": "//dl[contains(@class,'torrent-info')]/dd[last()]/text()" 46 | } 47 | ], 48 | "time": [ 49 | { 50 | "type": null, 51 | "default": "2000-00-00" 52 | } 53 | ] 54 | } 55 | } -------------------------------------------------------------------------------- /rule/cursor.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "cursor", 3 | "name": "吃力网", 4 | "desc": "", 5 | "proxy": false, 6 | "publish": "https://cursor.vip/vip", 7 | "publishMail": "", 8 | "url": "https://www.sokankan2.cc", 9 | "referer": "https://www.sokankan2.cc", 10 | "path": { 11 | "default": "/search/{k}/page-{p}.html" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='list-view']/article[@class='item' and @data-key]", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": null, 22 | "default": 0 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "xpath", 28 | "xpath": "//a/@href" 29 | }, 30 | { 31 | "type": "subIndex", 32 | "start": -45, 33 | "end": -5 34 | } 35 | ], 36 | "name": [ 37 | { 38 | "type": "xpath", 39 | "xpath": "//h4/text()" 40 | } 41 | ], 42 | "hot": [ 43 | { 44 | "type": "xpath", 45 | "xpath": "//p[1]/text()" 46 | }, 47 | { 48 | "type": "regex", 49 | "regex": "Hot:([\\d.]+)" 50 | } 51 | ], 52 | "size": [ 53 | { 54 | "type": "xpath", 55 | "xpath": "//p[1]/text()" 56 | }, 57 | { 58 | "type": "regex", 59 | "regex": "Size:([\\d.]+\\s[A-Z].)" 60 | } 61 | ], 62 | "time": [ 63 | { 64 | "type": "xpath", 65 | "xpath": "//p[1]/text()" 66 | }, 67 | { 68 | "type": "regex", 69 | "regex": "Created:(\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2})" 70 | } 71 | ] 72 | } 73 | } -------------------------------------------------------------------------------- /rule/sofan.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "sofan", 3 | "name": "搜番", 4 | "desc": "", 5 | "proxy": false, 6 | "publish": "https://sofan.icu", 7 | "publishMail": "lauchichoy@south.flyzoohotel.com.cn", 8 | "url": "https://fan1.yun55.top:65533", 9 | "referer": "https://fan1.yun55.top:65533/?host=a4.fan55.top", 10 | "path": { 11 | "default": "/s?word={k}&page={p}" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='container-fluid']//ul[@class='list-unstyled']", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": null, 22 | "default": 0 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "xpath", 28 | "xpath": "//ul[@class='list-unstyled']/@id" 29 | } 30 | ], 31 | "name": [ 32 | { 33 | "type": "xpathList", 34 | "xpath": "//h3/a//text()" 35 | } 36 | ], 37 | "hot": [ 38 | { 39 | "type": "xpath", 40 | "xpath": "//li[@class='result-resource-meta-info']/span[4]/text()" 41 | } 42 | ], 43 | "size": [ 44 | { 45 | "type": "xpath", 46 | "xpath": "//li[@class='result-resource-meta-info']/span[1]/text()" 47 | } 48 | ], 49 | "time": [ 50 | { 51 | "type": "xpath", 52 | "xpath": "//li[@class='result-resource-meta-info']/span[3]/text()" 53 | } 54 | ] 55 | } 56 | } -------------------------------------------------------------------------------- /rule/zhongziso.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "zhongziso", 3 | "name": "种子搜", 4 | "desc": "", 5 | "proxy": false, 6 | "publish": "https://www.zhongzidizhi.com/", 7 | "publishMail": "", 8 | "url": "https://m.zhongziso23.xyz", 9 | "referer": "https://m.zhongziso23.xyz", 10 | "path": { 11 | "default": "/list_ctime/{k}/{p}" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//div[@class='panel-body']/ul[@class='list-group']", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": null, 22 | "default": 0 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "xpath", 28 | "xpath": "//a[@class='text-success']/@href" 29 | }, 30 | { 31 | "type": "subIndex", 32 | "start": -40, 33 | "end": null 34 | } 35 | ], 36 | "name": [ 37 | { 38 | "type": "xpathList", 39 | "xpath": "//a[@class='text-success']//text()" 40 | } 41 | ], 42 | "hot": [ 43 | { 44 | "type": null, 45 | "default": 99 46 | } 47 | ], 48 | "size": [ 49 | { 50 | "type": "xpath", 51 | "xpath": "//dl[@class='list-code']/dd[2]/text()" 52 | } 53 | ], 54 | "time": [ 55 | { 56 | "type": "xpath", 57 | "xpath": "//dl[@class='list-code']/dd[3]/text()" 58 | } 59 | ] 60 | } 61 | } -------------------------------------------------------------------------------- /rule/zooqle.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "zooqle", 3 | "name": "Zooqle", 4 | "desc": "【优】【英文】【支持中文搜索】", 5 | "proxy": false, 6 | "publish": "", 7 | "publishMail": "", 8 | "url": "https://zooqle.com", 9 | "referer": "https://zooqle.com", 10 | "path": { 11 | "default": "/search?pg={p}&q={k}&v=t" 12 | }, 13 | "parse": { 14 | "item": { 15 | "type": "xpath", 16 | "xpath": "//tbody/tr", 17 | "startIndex": 0 18 | }, 19 | "page": [ 20 | { 21 | "type": "xpath", 22 | "xpath": "//ul[contains(@class,'pagination')]/li[last()-2]/a/text()" 23 | } 24 | ], 25 | "magnet": [ 26 | { 27 | "type": "xpath", 28 | "xpath": "//a[@title='Magnet link']/@href" 29 | } 30 | ], 31 | "name": [ 32 | { 33 | "type": "xpathList", 34 | "xpath": "//td/a[@class=' small']//text()" 35 | } 36 | ], 37 | "hot": [ 38 | { 39 | "type": "xpath", 40 | "xpath": "//td[@class='text-nowrap smaller']//div[contains(@class,'prog-green')]/text()" 41 | } 42 | ], 43 | "size": [ 44 | { 45 | "type": "xpath", 46 | "xpath": "//td[@class='smaller']//text()" 47 | } 48 | ], 49 | "time": [ 50 | { 51 | "type": "xpath", 52 | "xpath": "//td[@class='text-nowrap text-muted smaller']/text()" 53 | } 54 | ] 55 | } 56 | } -------------------------------------------------------------------------------- /toolchain/navigation.txt: -------------------------------------------------------------------------------- 1 | 聚BT 2 | 地址发布:https://1jubt.top/ 3 | 最新网址:https://jubt.live/cn/index.html 4 | 5 | 6 | -------------------------------------------------------------------------------- /toolchain/update_rule.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import requests 4 | import codecs 5 | import json 6 | 7 | 8 | # 更新规则数据 9 | def gen_rules(): 10 | url = 'https://magnetw.app/rule.json' 11 | rule_json = requests.get(url) 12 | open('rule.json', 'wb').write(rule_json.content) 13 | 14 | with open('rule.json', encoding='utf-8') as f: 15 | rule_list = json.load(f) 16 | for rule in rule_list: 17 | fp = codecs.open('../rule/resource/' + rule['id'] + '.json', 'w', 'utf-8') 18 | fp.write(json.dumps(rule, ensure_ascii=False, sort_keys=False, indent=2, separators=(', ', ': '))) 19 | 20 | 21 | # 生成UI结构(弃用) 22 | def gen_list_model(): 23 | file_path = '../rule' 24 | file_list = os.listdir(file_path) 25 | 26 | model_str = '' 27 | for file in file_list: 28 | if os.path.isfile(file_path + '/' + file): 29 | with open(file_path + '/' + file, encoding='utf-8') as f: 30 | rule_obj = json.load(f) 31 | model_str += ''' 32 | ListElement { 33 | key: '%s' 34 | value: '%s' 35 | }''' % (rule_obj['id'], rule_obj['name']) 36 | 37 | print(model_str) 38 | 39 | 40 | # 规则文件地址 41 | # https://magnetw.app/rule.json 42 | if __name__ == '__main__': 43 | print('规则相关工具链') 44 | gen_list_model() 45 | # gen_rules() 46 | -------------------------------------------------------------------------------- /toolchain/website.txt: -------------------------------------------------------------------------------- 1 | https://102433.tk 2 | https://2048btt.tk(2048bt.top,2048bt.cyou,bt搜索.xyz,bt搜索.cc) 3 | https://bthub36.xyz 4 | https://5z6v65pa.xyz 5 | https://www.yuhuage13.xyz 6 | https://zhongziso24.xyz 7 | https://katcr.to 8 | https://kickass.cd 9 | https://ccligou.gq 10 | 11 | 12 | 13 | https://torrentzeu.org/ 14 | https://nyaa.eu/ 15 | 16 | 地址发布 17 | https://wangzhi.men/bthaha/ -------------------------------------------------------------------------------- /toolchain/website_update.py: -------------------------------------------------------------------------------- 1 | # http://axutongxue.com/ 2 | def get_all(): 3 | pass 4 | 5 | 6 | if __name__ == '__main__': 7 | get_all() 8 | -------------------------------------------------------------------------------- /user_agent.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | ua_list = [ 4 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36', 5 | 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/44.0.2403.155 Safari/537.36', 6 | 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36', 7 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36', 8 | 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36', 9 | 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36', 10 | 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36', 11 | 'Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36', 12 | 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36', 13 | 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36', 14 | 'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36', 15 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36', 16 | 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36', 17 | 'Mozilla/5.0 (Windows NT 4.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36', 18 | 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36', 19 | 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36', 20 | 'Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36', 21 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36', 22 | 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.3319.102 Safari/537.36', 23 | 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2309.372 Safari/537.36', 24 | 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2117.157 Safari/537.36', 25 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36', 26 | 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1866.237 Safari/537.36', 27 | 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/4E423F', 28 | 'Mozilla/5.0 (X11; Linux i686; rv:64.0) Gecko/20100101 Firefox/64.0', 29 | 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0', 30 | 'Mozilla/5.0 (X11; Linux i586; rv:63.0) Gecko/20100101 Firefox/63.0', 31 | 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:63.0) Gecko/20100101 Firefox/63.0', 32 | 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.10; rv:62.0) Gecko/20100101 Firefox/62.0', 33 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:10.0) Gecko/20100101 Firefox/62.0', 34 | 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.13; ko; rv:1.9.1b2) Gecko/20081201 Firefox/60.0', 35 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/58.0.1', 36 | 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/58.0', 37 | 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:52.59.12) Gecko/20160044 Firefox/52.59.12', 38 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9a1) Gecko/20060814 Firefox/51.0', 39 | 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/20120121 Firefox/46.0', 40 | 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.66.18) Gecko/20177177 Firefox/45.66.18', 41 | 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1', 42 | 'Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0', 43 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0', 44 | 'Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/31.0', 45 | 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20130401 Firefox/31.0', 46 | 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:28.0) Gecko/20100101 Firefox/31.0', 47 | 'Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0', 48 | 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20120101 Firefox/29.0', 49 | 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/29.0', 50 | 'Mozilla/5.0 (X11; OpenBSD amd64; rv:28.0) Gecko/20100101 Firefox/28.0', 51 | 'Mozilla/5.0 (X11; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0', 52 | 'Mozilla/5.0 (Windows NT 6.1; rv:27.3) Gecko/20130101 Firefox/27.3', 53 | 'Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:27.0) Gecko/20121011 Firefox/27.0', 54 | 'Mozilla/5.0 (Windows NT 6.2; rv:20.0) Gecko/20121202 Firefox/26.0', 55 | 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0', 56 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0', 57 | 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0', 58 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14931', 59 | 'Chrome (AppleWebKit/537.1; Chrome50.0; Windows NT 6.3) AppleWebKit/537.36 (KHTML like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393', 60 | 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.9200', 61 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586', 62 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246', 63 | 'Mozilla/5.0 (Windows; U; Windows NT 6.1; rv:2.2) Gecko/20110201', 64 | 'Mozilla/5.0 (Windows; U; Windows NT 6.1; it; rv:2.0b4) Gecko/20100818', 65 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9a3pre) Gecko/20070330', 66 | 'Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.9.2a1pre) Gecko', 67 | 'Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.2.3) Gecko/20100401 Lightningquail/3.6.3', 68 | 'Mozilla/5.0 (X11; ; Linux i686; rv:1.9.2.20) Gecko/20110805', 69 | 'Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 iPhone', 70 | 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.13; ) Gecko/20101203', 71 | 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1b3) Gecko/20090305', 72 | 'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.0.9) Gecko/2009040821', 73 | 'Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.0.8) Gecko/2009032711', 74 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.7) Gecko/2009032803', 75 | 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.0.7) Gecko/2009021910 MEGAUPLOAD 1.0', 76 | 'Mozilla/5.0 (Windows; U; BeOS; en-US; rv:1.9.0.7) Gecko/2009021910', 77 | 'Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.6) Gecko/2009020911', 78 | 'Mozilla/5.0 (X11; U; Linux i686; en; rv:1.9.0.6) Gecko/20080528', 79 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.6) Gecko/2009020409', 80 | 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.3) Gecko/2008092814 (Debian-3.0.1-1)', 81 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092816', 82 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008090713', 83 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.2) Gecko Fedora/1.9.0.2-1.fc9', 84 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.14) Gecko/2009091010', 85 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.10) Gecko/2009042523', 86 | 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.1) Gecko/2008072610', 87 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008072820 Ubuntu/8.04 (hardy) (Linux Mint)', 88 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko', 89 | 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.1) Gecko/2008070206', 90 | 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-au; rv:1.9.0.1) Gecko/2008070206', 91 | 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko', 92 | 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9) Gecko', 93 | 'Mozilla/5.0 (Windows; U; Windows NT 5.1; cs; rv:1.9) Gecko/2008052906', 94 | 'Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b2) Gecko/20050702', 95 | 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050217', 96 | 'Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.8b) Gecko/20050217', 97 | 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050217', 98 | 'Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8a6) Gecko/20050111', 99 | 'Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.8a5) Gecko/20041122', 100 | 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a4) Gecko/20040927', 101 | 'Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.8a4) Gecko/20040927', 102 | 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040817', 103 | 'Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16', 104 | 'Opera/9.80 (Macintosh; Intel Mac OS X 10.14.1) Presto/2.12.388 Version/12.16', 105 | 'Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14', 106 | 'Mozilla/5.0 (Windows NT 6.0; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 12.14', 107 | 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0) Opera 12.14', 108 | 'Opera/12.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.02', 109 | 'Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00', 110 | 'Opera/9.80 (Windows NT 5.1; U; zh-sg) Presto/2.9.181 Version/12.00', 111 | 'Opera/12.0(Windows NT 5.2;U;en)Presto/22.9.168 Version/12.00', 112 | 'Opera/12.0(Windows NT 5.1;U;en)Presto/22.9.168 Version/12.00', 113 | 'Mozilla/5.0 (Windows NT 5.1) Gecko/20100101 Firefox/14.0 Opera/12.0', 114 | 'Opera/9.80 (Windows NT 6.1; WOW64; U; pt) Presto/2.10.229 Version/11.62', 115 | 'Opera/9.80 (Windows NT 6.0; U; pl) Presto/2.10.229 Version/11.62', 116 | 'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52', 117 | 'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; de) Presto/2.9.168 Version/11.52', 118 | 'Opera/9.80 (Windows NT 5.1; U; en) Presto/2.9.168 Version/11.51', 119 | 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; de) Opera 11.51', 120 | 'Opera/9.80 (X11; Linux x86_64; U; fr) Presto/2.9.168 Version/11.50', 121 | 'Opera/9.80 (X11; Linux i686; U; hu) Presto/2.9.168 Version/11.50', 122 | 'Opera/9.80 (X11; Linux i686; U; ru) Presto/2.8.131 Version/11.11', 123 | 'Opera/9.80 (X11; Linux i686; U; es-ES) Presto/2.8.131 Version/11.11', 124 | 'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/5.0 Opera 11.11', 125 | 'Opera/9.80 (X11; Linux x86_64; U; bg) Presto/2.8.131 Version/11.10', 126 | 'Opera/9.80 (Windows NT 6.0; U; en) Presto/2.8.99 Version/11.10', 127 | 'Opera/9.80 (Windows NT 5.1; U; zh-tw) Presto/2.8.131 Version/11.10', 128 | 'Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1', 129 | 'Opera/9.80 (X11; Linux x86_64; U; Ubuntu/10.10 (maverick); pl) Presto/2.7.62 Version/11.01', 130 | 'Opera/9.80 (X11; Linux i686; U; ja) Presto/2.7.62 Version/11.01', 131 | 'Opera/9.80 (X11; Linux i686; U; fr) Presto/2.7.62 Version/11.01', 132 | 'Opera/9.80 (Windows NT 6.1; U; zh-tw) Presto/2.7.62 Version/11.01', 133 | 'Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.7.62 Version/11.01', 134 | 'Opera/9.80 (Windows NT 6.1; U; sv) Presto/2.7.62 Version/11.01', 135 | 'Opera/9.80 (Windows NT 6.1; U; en-US) Presto/2.7.62 Version/11.01', 136 | 'Opera/9.80 (Windows NT 6.1; U; cs) Presto/2.7.62 Version/11.01', 137 | 'Opera/9.80 (Windows NT 6.0; U; pl) Presto/2.7.62 Version/11.01', 138 | 'Opera/9.80 (Windows NT 5.2; U; ru) Presto/2.7.62 Version/11.01', 139 | 'Opera/9.80 (Windows NT 5.1; U;) Presto/2.7.62 Version/11.01', 140 | ] 141 | 142 | 143 | def random_ua(): 144 | return random.choice(ua_list) 145 | --------------------------------------------------------------------------------