Gite
Github


还有部分站点明文规定不允许使用自动化工具的,请各位慎用,谨防ban号

主要功能

  • 自动签到
  • 自动刷新个人数据
  • 自动拉取站点首页促销种子
  • 可以自定义自动任务,内置定时任务,7小时一次签到,6小时一次抓取个人数据,2小时拉取一次最新种子,可以更改执行频- 率,但是不支持直接更改具体执行时间,支持corn表达式
  • 允许推送种子到下载器,支持QB和TR,但QB仅支持推送,目前不支持与种子关联
  • 支持使用ptpp的备份文件导入站点
  • 实现对qb下载器的集中管理
    ps:提醒,其他自动任务目前为空壳,请勿使用

运行机制

  • 为了压缩镜像体积,整个镜像内,我只添加了一个文件:start.sh,这个文件的作用就是从gitee下载ptools的代码,并安装依赖,所以第一次启动时间会比较长,请耐心等待
  • 第一次启动以后,依赖就安装完了,但是以后每次启动都会运行一遍依赖检测,一是更新依赖,二是新代码可能会增加新的依赖,但耗时就很短了,不用担心每次启动都要很久
  • 更新代码时会备份数据库,所以不必担心数据会出问题

安装

-v 本地路径:容器路径,后面的是数据库路径/ptools/db,后面不能改

# -v 本地路径:容器路径,下面的是数据库路径/ptools/db,后面不能改
# -v docker、docker.sock 映射,用于实现点击页面按钮重启容器更新代码,:前的路径需要根据实际情况更改,获取路径命令:`which docker`
# -p 端口映射,本地端口:容器端口,后面不能改
# -e 设置环境变量,这里用于配置工具登录账号和密码,可以删掉不写,会有默认值,在登录一项有写,登录之后都可以修改 
# DJANGO_SUPERUSER_USERNAME:用户名 
# DJANGO_SUPERUSER_EMAIL 邮箱 
# DJANGO_SUPERUSER_PASSWORD:密码
# DJANGO_WEB_PORT:自定义容器内部端口,用户HOST网络模式,一般不需要使用
# DEV: 参数 master/dev,默认master稳定分支,可以设置为dev访问开发分支
# HTTPS_DOMAINS:用于设定反向代理域名,默认为空,如需设置,请填写完整域名,如:https://ptools.baidu.com

# 最简单的部署
docker run -d \
-v /your-path/db:/ptools/db \
-p 8001:8000 \
ngfchl/ptools
# 直接自定义用户名密码
docker run -d \
-v /your-path/db:/ptools/db \
-p 8001:8000 \
-e DJANGO_SUPERUSER_USERNAME=admin \
-e [email protected] \
-e DJANGO_SUPERUSER_PASSWORD=adminadmin \
ngfchl/ptools

# 映射docker路径,实现容器内直接重启本容器,需要使用 which docker 自行查找docker路径
docker run -d \
-v /your-path/db:/ptools/db \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
-p 8001:8000 \
--name=ptools \
ngfchl/ptools
# 宝塔
docker run -itd -v /www/wwwroot/ptools/db:/ptools/db  -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -p 8001:8000 --name=ptools ngfchl/ptools
# 群晖,群晖一定不要在root模式下搞,要使用sudo命令执行
sudo docker run -itd -v /volume1/docker/ptools/db:/ptools/db  -v /var/run/docker.sock:/var/run/docker.sock -v /usr/local/bin/docker:/usr/bin/docker -p 8001:8000 --name=ptools ngfchl/ptools

群晖安装

下载镜像:ngfchl/ptools
image
下载成功,点击启动
image
配置容器,提前准备好文件夹,我的路径:volume1/docker/ptools
image
选择网络,默认就好,不需要用host模式,但是,如果你的网络环境比较差,或者需要使用IP V6,那你最好使用HOST模式,连接性更好,并且与主机共享V6地址
image
取好名字,开启自动重启
image
打开高级设置,环境变量里面设置这三项就可以了,如果你使用host模式,而且端口8000与其他应用有冲突,可以修改最下方的WEB_PORT为你喜欢的端口,保存,下一步
image
配置访问端口,这里填上你喜欢的端口,host模式无需配置,未修改环境变量就是8000,修改了就是你修改的值。
image
映射数据库文件夹,选择你想保存的文件夹,然后填上容器内部的路径:/ptools/db,这个路径是固定的,当然如果你懂docker,你看着搞就行
image

**** 映射路径已更改为/ptools/db,请知悉
image
下一步,完成启动容器,在容器状态中就可以查看日志了,也可以在终端机查看实时日志
image
等待系统提示如下信息,就启动完成了!玩得开心
image

极空间安装

搜索并下载镜像
image

设置并启动容器
image

映射文件夹,装载路径必须为:/ptools/db ,不可更改,映射路径已更改为/ptools/db,请知悉
image

端口映射,本地端口看你喜欢,容器端口必须为8000,如果你使用HOST模式,这一步无需映射
image

环境变量设置,默认可以不用设置,但是如果你使用HOST模式,需要更改端口,可以在这里修改环境变量DJANGO_WEB_PORT为你喜欢的端口
image

其他选项无需更改,保存启动,访问你配置的端口即可。

UNRAID模板使用

点击下载模板文件

请注意这里,下载方式如下,在页面的原始数据上点击右键=》链接另存为

image

下载文件后,导入到unraid的/root/.docker/templates-user目录下(工具为:finalshell)
image

然后在创建容器时选择ptools就可以使用模板创建了
image

根据需要修改自己的参数
image

点击应用,安装完毕。

登录后台

默认密码如下,可以在环境变量中自行设置登录账号密码,也可以不设置用户名密码,登录之后自行更改

• 默认端口:8000

• 默认用户名:admin

• 默认 密码:adminadmin

更新功能

• 大版本更新
暂时不会又大版本更新,但是会不定期更新基础镜像,没有特殊提醒,可以不用更新镜像。
• 小版本更新
小版本更新直接在网页上操作即可:更新与导入 => 代码更新,进入页面后点击更新即可,提示错误就再点击一次
image

站点支持

image

错误处理

无法登陆、更新出错之提示密码错误处理

• 第一次登录修改账号密码之后,一定要记牢了,不小心删除数据库文件也会报密码错误,流程都是相似的,自行琢磨一下

• 更新出错再第3步跳转到第5步进行即可

命令行方式处理

• 进入宿主机命令行

• 查找容器ID:sudo docker ps -a
image
• 进入容器命令行:docker exec -it 9a1c6bdafe9a /bin/bash

• 进入项目文件夹:cd /ptools

• 创建用户或修改密码

提醒:输入密码无回显,即无***,输入完确认即可

• 修改密码命令:python manage.py changepassword 你的用户名

• 创建用户命令:python manage.py createsuperuser

• 如果是更新页面出错,执行命令: git pull && python manage.py migrate

然后访问你的路径/tasks/do_update

群晖进入终端

在容器详情中进入终端机,点击新增,即可在右侧输入命令,之后从上方第三步开始
image

image

威联通进入终端

image

unraid进入终端

image
image

PTPP导入功能

• PTPP备份设置
◊ 备份时备份cookie
image

◊ 给予cookie权限
image

• 打开PTPP助手的参数备份与恢复
image

• 生成备份
image

• 进入PTools导入界面
image
image

• 选择刚刚备份的文件,点击导入,等待返回结果即可
image

百度OCR识别

百度OCR通用文字识别的API,请自行百度获取

在计划任务中打开OCR识别
image

image

选择增加,按要求填入字段,并勾选启用,保存即可

自行适配

通用规则

◊ 这里我做了NP架构站点的信息获取的通用XPATH
◊ 只要界面只是轻微改动的站点大部分能用,大家可以自行尝试一下,如果可以用,可以群里告诉我,我把站点加到支持列表
◊ 懂XPATH的大佬们可以参与一下,很简单的。

# 用户等级
//table[@id="info_block"]//span/a[contains(@class,"_Name") and contains(@href,"userdetails.php?id=")]/@class
U2: //img[contains(@src,"user")]/@src
TTG: //td[contains(text(),"等级")]/following-sibling::td/text()
SSD: //div[@id="info_block"]//a[contains(@href,"userdetails.php?id=")]//span/@class
# 用户ID
//table[@id="info_block"]//span/a[contains(@class,"_Name") and contains(@href,"userdetails.php?id=")]/@href

ttg://h1/a[contains(@href,"userdetails.php?id=")]/@href

# 用户passkey
//td[contains(text(),"Passkey")]/following-sibling::td[1]/text()
//td[contains(text(),"密钥")]/following-sibling::td[1]/text()
//td[contains(text(),"密匙")]/following-sibling::td[1]/text()
观众://td[contains(text(),"密钥")]/following-sibling::td[1]/span/text()
U2://td[contains(text(),"密钥")]/following-sibling::td[1]/span/@data-content
# 分享率
//font[@class="color_ratio"][1]/following-sibling::text()[1]

TTG: //font[contains(text(),"分享率 ")][1]/following-sibling::font[1]/text()[1]
U2://span[contains(text(),"分享率")][1]/following-sibling::text()[1]
南洋、芒果://img[@alt="Ratio"][1]/following-sibling::text()[1]

# 魔力值
//a[@href="mybonus.php"]/following-sibling::text()[1]
//a[contains(@href,"mybonus.php")]/following-sibling::text()[1]

U2: //a[@href="ucoin.php"]/following-sibling::span[1]//text()
南洋、TTG: //a[contains(@href,"mybonus.php")]/text()[1]
joyhd://a[@href="usebonus.php"]/following-sibling::text()[1]
# 时魔
//div[contains(text(),"每小时")]/text()[1]
mt://td[contains(text(),"每小")]/text()[1]
U2: //td[@id="outer"]//td[@class="text"]/text()
TTG: //td[contains(text(),"总计")]/following-sibling::td/text()
# 做种积分
//font[@class="color_bonus" and contains(text(),"积分")]/following-sibling::text()[1]

TTG => HP: 
观众://a[contains(@href,"blackjack.php")]/following-sibling::text()[1]

# 邀请
//span/a[contains(@href,"invite.php?id=")]/following-sibling::text()[1]

TTG: //a[contains(@href,"invite.php")]/span/text()[1]
南洋、芒果://span/a[contains(@href,"invite.php")]/text()[1]

# 上传量
//font[@class="color_uploaded"]/following-sibling::text()[1]
TTG://font[contains(text(),"上传量")]/following-sibling::font[1]/a/text()[1]
U2: //span[@class="color_uploaded"]/following-sibling::text()[1]
# 下载量
//font[@class="color_downloaded"]/following-sibling::text()[1]
U2: //span[@class="color_downloaded"]/following-sibling::text()[1]
TTG://font[contains(text(),"下载量")]/following-sibling::font[1]/a/text()[1]
# 当前做种数
###  <img class="arrowup" alt="Torrents seeding" title="当前做种" src="pic/trans.gif">
//img[@class="arrowup"][1]/following-sibling::text()[1]
南洋://img[@alt="Torrents seeding"][1]/following-sibling::text()[1]
TTG://img[contains(@title,"做种中")]/following-sibling::font[1]/span/text()[1]
U2: .//a[contains(@href,"#seedlist")]//text()
# 当前下载数
//img[@class="arrowdown"][1]/following-sibling::text()[1]

南洋://img[@alt="Torrents leeching"][1]/following-sibling::text()[1]
TTG://img[contains(@title,"下载中")]/following-sibling::font[1]/span/text()[1]
# HR
//a[@href="myhr.php"]//text()
//a[contains(@href,"myhr.php")]//text()
# 邮件
20220911更新
//a[@href="messages.php"]/font[contains(text(),"条")]/text()[1]

//a[@href="messages.php"]/font/text()[1]

TTG : //img[@alt="inbox"]/parent::a[contains(@href,"messages.php")]/following-sibling::text()[1]

# 注册日期
//td[contains(text(),"加入")]/following-sibling::td[1]//span/@title
U2://td[contains(text(),"加入")]/following-sibling::td[1]//time/@title
TTG: //td[contains(text(),"注册日期")]/following-sibling::td[1]/text()

# 最近活动日期
//td[contains(text(),"最近")]/following-sibling::td[1]//span/@title
U2: //td[contains(text(),"最近")]/following-sibling::td[1]//time/@title
TTG://td[contains(text(),"上次访问")]/following-sibling::td[1]/text()

# 当前做种记录数、做种体积  pop(0)去除标题行,len获取记录数,获取的体积相加为做种体积
//tr/td[4]

U2/mt/joyhd://tr/td[3]



# 种子表格
//table[@class="torrents"]/tr

# 种子名称 name_rule
.//td[@class="embedded"]/a/b//text()
ttg: .//div[@class="name_left"]/a/b/span/text()
猫:.//td[@class="embedded"]//a[contains(@href,"detail")]/@title

# 种子标题
.//td[@class="embedded"]/a[contains(@href,"detail")]/parent::td/span[last()]/text()
.//td[@class="embedded"]/a[contains(@href,"detail")]/following::text()[1]
ttg: .//div[@class="name_left"]/a/b/text()[1]
南洋:.//td[@class="embedded"]/a[contains(@href,"detail")]/parent::td/text()
joyhd:.//td[@class="embedded"]/a[contains(@href,"detail")]/following::text()[2]
猫:.//td[@class="embedded"]//a[contains(@href,"detail")]/parent::div/following-sibling::div/span[last()]/text()
# 详情页
.//td[@class="embedded"]/a[contains(@href,"detail")]/@href
ttg: .//div/a[contains(@href,"/t/")]/@href
# 分类
.//td[@class="rowfollow nowrap"][1]/a[1]/img/@title
.//td[@class="rowfollow nowrap"][1]/a[1]/img/@alt
.//td[@class="rowfollow nowrap"][1]/a[1]/img/@class
ttg: .//img[contains(@src,"cate")]/@alt
joyhd:.//td[@class="rowfollow nowrap"][1]/span/a[1]/img/@class
# 海报
无
# 首页行内下载链接 magnet 链接 magnet_url
.//a[contains(@href,"download.php?id=")]/@href
ttg: .//img[contains(@class,"dl_img")]/parent::a/@href
# 详情页下载链接
.//a[contains(@href,"download.php?") and contains(text(),"右键")]/@href
南洋://a[contains(@href,"download.php?") and contains(text(),"右键")]/@href
月月:  .//input[@id="download_link"]/@value 
TTG://a[contains(text(),"点击复制")]/@href
吐鲁番:.//a[contains(@href,"download.php?id=") and contains(@href,"passkey")]/@href

老师:.//a[contains(@href,"download.php?downhash=")]/@href

# 文件大小
.//td[5]//text()
# HR
无
# 促销
# .//div/img[contains(@class,"pro_")]/@alt
.//img[contains(@class,"pro_")]/@alt
ttg: .//img[contains(@src,"free")]/@alt
吐鲁番:  .//img[contains(@class,"pro_")]/@alt
# 或许可以为默认?
joyhd:.//img[contains(@class,"free")]/@alt
# 促销结束时间
# .//div/img[contains(@class,"pro_")]/@onmouseover
.//img[contains(@class,"free")]/following-sibling::font/span/@title
吐鲁番:.//img[contains(@class,"pro_")]/following::span[1]/@title

# 发布时间
.//td[4]/span/@title
南洋:.//td[4]/text()

# 做种人数
.//a[contains(@href,"#seeders")]/text()
.//a[contains(@href,"#seeders")]//text()
ttg: .//a[contains(@href,"&toseeders")]//text()
# 下载人数,无结果的为0
.//a[contains(@href,"#leechers")]/text()
.//a[contains(@href,"#leechers")]//text()
# 完成人数
.//a[contains(@href,"viewsnatches")]//text()
ttg: .//td[8]/text()[1]
# 平均完成进度
.//tr/td[9]/nobr/text()

吐鲁番:.//tr/td[8]/nobr/text()
# 平均下载速度
.//b[contains(text(),"下载者")]/parent::font/following-sibling::table/tr/td[6]/nobr/text()

# hash
//td[@class="no_border_wide"]/b[contains(text(),"Hash 码")]/following::text()[1]
//td/b[contains(text(),"Hash")]/following::text()[1]

适配教程

◊ 登录站点,进入个人主页

◊ F12打开开发者工具,选择元素选项,在内容上点一下
image
◊ ctrl+F或者command+F打开查找框

image

◊ 把XPATH规则填入进去按回车,后面会显示当前找到了几条元素,如果是1/1,恭喜,规则可以用,如果是0就是没找到,有很多条就是有很多规则相同的元素,需要自行分析一下修改规则,上面示例中就是在种子详情页获取种子下载链接的Xpath(获取页面中的a链接的网址,指定a链接的网址中包含download.php和passkey字段)

tips:

xpath查找时,浏览器要识别tbody,代码中需要将tbody去掉

/表示从根节点开始,//开始表示全文查找,./代表当前节点开始找,获取个人数据可以用//

测试教程

  1. 登录PTools => PT站点管理 => 站点信息 => 增加,填入下图字段,保存
    image-1668652470305
  2. 我的站点=> 增加 => 用户信息=>显示,选择刚刚添加的站点,填入UID和cookie,保存。
    image-1668652622864
  3. 保存后回到我的站点,选中刚刚添加的站点,测试签到,更新数据等功能
    image-1668652730649

    测试站点,点击签到或者更新数据或拉取种子(一次只选一个站点,只点一个功能,否则容易冲突)

通知推送

支持的通知方式

  • 企业微信通知,可信IP可以百度IP,将获取到的IP填进去

  • wxpusher

  • pushdeer

  • bark

  • 爱语飞飞

添加教程

  1. 打开计划任务=>通知推送

  2. 点击增加,选择你需要的通知方式

image-1668653080979

  1. 根据需要填写相关API信息对应关系如下,留空的无需填写,写明内容的必填
企业微信 WxPusher Bark PushDeer 爱语飞飞
id 企业ID 可不填
secret Secret token Token token token
app_id 应用ID app_id
user 接收者 用户uid
server 必填https://api.day.app/ 必填http://iyuu.cn/
提醒 保留最后的“/” 保留最后的“/”

如需使用对应通知,记得勾选开启哦。