Skip to content

Commit

Permalink
v1.0 增加HR筛选,增强稳定性,增加站点支持
Browse files Browse the repository at this point in the history
  • Loading branch information
Juszoe committed Aug 13, 2019
1 parent 257e1e7 commit 885939f
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 75 deletions.
33 changes: 26 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,22 @@ C:\Users\<YOURUSER>\flexget\plugins\ # Windows
1. 编辑flexget配置文件,添加nexusphp选项,按照需要进行配置
``` yaml
nexusphp:
cookie: 'you_cookie'
discount:
cookie: 'you_cookie' # 必填
discount: # 优惠信息 选填
- free
- 2x
- 2x50%
- 2xfree
- 50%
- 30%
seeders:
seeders: # 做种情况 选填
min: 1
max: 2
leechers:
leechers: # 下载情况 选填
min: 10
max: 100
max_complete: 0.8
hr: no # 是否下载HR 选填
```
2. 为rss的other_fields字段添加link属性
``` yaml
Expand Down Expand Up @@ -72,12 +73,14 @@ flexget execute
数字,最大下载人数,默认不限制
#### `max_complete`
小数,范围`0-1.0` 下载者中最大完成度,超过这个值将不下载,默认为1
### hr
yes或no,是否下载HR,默认不考虑HR,即可能下载到HR

## 完整配置示例
### 免费热种
``` yaml
tasks:
task_name:
my-free-task:
rss:
url: https://www.example.com/rss.xml
other_fields:
Expand All @@ -98,7 +101,7 @@ tasks:
### 热种
``` yaml
tasks:
task_name:
my-hot-task:
rss:
url: https://www.example.com/rss.xml
other_fields:
Expand All @@ -111,6 +114,19 @@ tasks:
min: 20
download: ~/flexget/torrents/
```
### 避免HR
``` yaml
tasks:
no-hr-task:
rss:
url: https://www.example.com/rss.xml
other_fields:
- link
nexusphp:
cookie: 'you_cookie'
hr: no
download: ~/flexget/torrents/
```
## 常见问题
#### 我的python版本是2.X如何使用?
Expand All @@ -125,9 +141,12 @@ pip3 install flexget # 使用pip3安装
以下站点名使用别称或简称,欢迎反馈更多可用或不可用的站点
- 任何未修改关键结构的nexusphp站点
- 铂金家
- 馒头
- 馒头(站点安全性较高,使用flexget ip与登录ip不同时可能无法使用)
- nice
- 菠萝
- OB
- 天空
- 学校

#### 如何判断站点是否支持
[判断站点以及适配站点](https://github.com/Juszoe/flexget-nexusphp/blob/master/site.md)
191 changes: 123 additions & 68 deletions nexusphp.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# coding=utf-8
from __future__ import unicode_literals, division, absolute_import
from builtins import *

import concurrent.futures

from requests.adapters import HTTPAdapter

from flexget import plugin
from flexget.config_schema import one_or_more
from flexget.event import event
Expand All @@ -10,6 +14,7 @@

class NexusPHP(object):
"""
配置示例
task_name:
rss:
url: https://www.example.com/rss.xml
Expand All @@ -27,6 +32,7 @@ class NexusPHP(object):
min: 1
max: 100
max_complete: 0.8
hr: no
"""

schema = {
Expand All @@ -37,18 +43,19 @@ class NexusPHP(object):
'seeders': {
'type': 'object',
'properties': {
'min': {'type': 'integer', 'minimum': 0},
'max': {'type': 'integer', 'minimum': 0}
'min': {'type': 'integer', 'minimum': 0, 'default': 0},
'max': {'type': 'integer', 'minimum': 0, 'default': 100000}
}
},
'leechers': {
'type': 'object',
'properties': {
'min': {'type': 'integer', 'minimum': 0},
'max': {'type': 'integer', 'minimum': 0},
'max_complete': {'type': 'number', 'minimum': 0, 'maximum': 1}
'min': {'type': 'integer', 'minimum': 0, 'default': 0},
'max': {'type': 'integer', 'minimum': 0, 'default': 100000},
'max_complete': {'type': 'number', 'minimum': 0, 'maximum': 1, 'default': 1}
}
}
},
'hr': {'type': 'boolean'}
},
'required': ['cookie']
}
Expand All @@ -57,20 +64,19 @@ def build_conifg(self, config):
config = dict(config)
config.setdefault('discount', None)
config.setdefault('seeders', {'min': 0, 'max': 100000})
config['seeders'].setdefault('min', 0)
config['seeders'].setdefault('max', 100000)
config.setdefault('leechers', {'min': 0, 'max': 100000, 'max_complete': 1})
config['leechers'].setdefault('min', 0)
config['leechers'].setdefault('max', 100000)
config['leechers'].setdefault('max_complete', 1)
config.setdefault('hr', None)
return config

@plugin.priority(-1)
def on_task_filter(self, task, config):
config = self.build_conifg(config)

adapter = HTTPAdapter(max_retries=5)
task.requests.mount('http://', adapter)
task.requests.mount('https://', adapter)

def consider_entry(_entry, _link):
discount, seeders, leechers = NexusPHP._get_info(task, _link, config['cookie'])
discount, seeders, leechers, hr = NexusPHP._get_info(task, _link, config['cookie'])
seeder_max = config['seeders']['max']
seeder_min = config['seeders']['min']
leecher_max = config['leechers']['max']
Expand All @@ -81,6 +87,10 @@ def consider_entry(_entry, _link):
_entry.reject('%s does not match discount' % discount) # 优惠信息不匹配
return

if config['hr'] is not None:
if hr != config['hr']:
_entry.reject('hr is %s' % hr) # HR信息不匹配

if len(seeders) not in range(seeder_min, seeder_max + 1):
_entry.reject('%d is out of range of seeder' % len(seeders)) # 做种人数不匹配
return
Expand Down Expand Up @@ -115,89 +125,134 @@ def consider_entry(_entry, _link):

@staticmethod
# 解析页面,获取优惠、做种者信息、下载者信息
def info_from_page(detail_page, peer_page):
def info_from_page(detail_page, peer_page, discount_fn=None, hr_fn=None):
soup = get_soup(detail_page.content, 'html.parser')
try:
discount_class = soup.find('h1', id='top').b.font['class'][0] # selector: '#top > b:nth-child(1) > font'
discount_table = {
'free': 'free',
'twoup': '2x',
'twoupfree': '2xfree',
'thirtypercent': '30%',
'halfdown': '50%',
'twouphalfdown': '2x50%'
}
discount = discount_table[discount_class]
except AttributeError:
if discount_fn is None:
def discount_fn(page):
convert = {
'free': 'free',
'twoup': '2x',
'twoupfree': '2xfree',
'thirtypercent': '30%',
'halfdown': '50%',
'twouphalfdown': '2x50%'
}
for key, value in convert.items():
if key in page.text:
return value
return None
discount = discount_fn(detail_page)
except Exception:
discount = None # 无优惠

def get_peers(table):
peers = []
name_index = 0
connectable_index = 1
uploaded_index = 2
downloaded_index = 4
completed_index = 7
for index, tr in enumerate(table.find_all('tr')):
try:
if index == 0:
tds = tr.find_all('td')
for i, td in enumerate(tds):
text = td.get_text()
if text == '用户' or text == '用戶':
name_index = i
elif text == '可连接' or text == '可連接':
connectable_index = i
elif text == '上传' or text == '上傳':
uploaded_index = i
elif text == '下载' or text == '下載':
downloaded_index = i
elif text == '完成':
completed_index = i
else:
tds = tr.find_all('td')
peers.append({
'name': tds[name_index].get_text(),
'connectable': True if tds[connectable_index].get_text() != '是' else False,
'uploaded': tds[uploaded_index].get_text(),
'downloaded': tds[downloaded_index].get_text(),
'completed': float(tds[completed_index].get_text().strip('%')) / 100
})
except IndexError:
pass
except ValueError:
pass
return peers
try:
if hr_fn:
hr = hr_fn(detail_page)
else:
# selector: '#top > img'
hr_class = soup.find('h1', id='top').img['class'][0]
hr = (hr_class == 'hitandrun')
except Exception:
hr = False # 无HR

soup = get_soup(peer_page.content)
tables = soup.find_all('table', limit=2)
try:
seeders = get_peers(tables[0])
seeders = NexusPHP.get_peers(tables[0])
except IndexError:
seeders = []
try:
leechers = get_peers(tables[1])
leechers = NexusPHP.get_peers(tables[1])
except IndexError:
leechers = []

return discount, seeders, leechers
return discount, seeders, leechers, hr

@staticmethod
def get_peers(table):
peers = []
name_index = 0
connectable_index = 1
uploaded_index = 2
downloaded_index = 4
completed_index = 7
for index, tr in enumerate(table.find_all('tr')):
try:
if index == 0:
tds = tr.find_all('td')
for i, td in enumerate(tds):
text = td.get_text()
if text == '用户' or text == '用戶':
name_index = i
elif text == '可连接' or text == '可連接':
connectable_index = i
elif text == '上传' or text == '上傳':
uploaded_index = i
elif text == '下载' or text == '下載':
downloaded_index = i
elif text == '完成':
completed_index = i
else:
tds = tr.find_all('td')
peers.append({
'name': tds[name_index].get_text(),
'connectable': True if tds[connectable_index].get_text() != '是' else False,
'uploaded': tds[uploaded_index].get_text(),
'downloaded': tds[downloaded_index].get_text(),
'completed': float(tds[completed_index].get_text().strip('%')) / 100
})
except Exception:
pass
return peers

@staticmethod
def _get_info(task, link, cookie):
headers = {
'cookie': cookie,
'accept-encoding': 'gzip, deflate',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/75.0.3770.142 Safari/537.36'
}
detail_page = task.requests.get(link, headers=headers, allow_redirects=False) # 详情
peer_url = link.replace('details.php', 'viewpeerlist.php', 1)
peer_page = task.requests.get(peer_url, headers=headers, allow_redirects=False) # peer详情

if detail_page.status_code == 302 or peer_page.status_code == 302:
if 'login' in detail_page.url or 'login' in peer_page.url:
raise plugin.PluginError("Can't access the site. Your cookie may be wrong!")

return NexusPHP.info_from_page(detail_page, peer_page)
if 'chdbits' in link:
def discount_fn(page):
convert = {
'pro_free': 'free',
'pro_2up': '2x',
'pro_free2up': '2xfree',
'pro_30pctdown': '30%',
'pro_50pctdown': '50%',
'pro_50pctdown2up': '2x50%'
}
for key, value in convert.items():
if key in page.text:
return value
return None
return NexusPHP.info_from_page(detail_page, peer_page, discount_fn)
if 'u2.dmhy' in link:
def discount_fn(page):
convert = {
'pro_free': 'free',
'pro_2up': '2x',
'pro_free2up': '2xfree',
'pro_30pctdown': '30%',
'pro_50pctdown': '50%',
'pro_50pctdown2up': '2x50%',
'pro_custom': '2x'
}
for key, value in convert.items():
if key in page.text:
return value
return None
return NexusPHP.info_from_page(detail_page, peer_page, discount_fn)
else:
return NexusPHP.info_from_page(detail_page, peer_page)


@event('plugin.register')
Expand Down
14 changes: 14 additions & 0 deletions site.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 判断站点支持程度
- 若发现日志输出大量none,可能该站点不支持,请联系开发者适配
```bash
REJECTED: `XXX` by nexusphp plugin because none does not match discount
```
- 该站点结构和其他站点区别较大,可能不支持

# 适配站点
请联系开发者并提供以下信息:
- 站点名
- Flexget相关输出日志
- 站点关键HTML结构截图,只需要free信息附近的HTML代码

`注意:提供信息时注意passkey`

0 comments on commit 885939f

Please sign in to comment.