[Python] 52破解的附件上传小工具
本帖最后由 QAQ~QL 于 2024-3-5 09:28 编辑# 52破解的附件上传
## 起因
2024春节题,本来用Typora自动picgo传上自己的七牛oss,发到论坛后发现很多地区都无法查看图片,遂手动使用论坛的图片功能传了将近50张图(4个帖子),并从html代码中提取了img的src网址,回到MD中**一一修改了img的网址**(真 ** 累啊)(后来发现自己是真傻啊,哈哈哈哈哈)
https://www.52pojie.cn/misc.php?mod=faq&action=faq&id=29&messageid=36
但是,由于上传图片返回的链接是临时链接,需要传到`附件/图片`点击附件,插入的`xxx`才是永久链接,遂又重新折腾了一遍,改到头皮发麻,于是诞生了该代码
## 代码
环境`pip install requests_toolbelt requests beautifulsoup4`
```python
import random
import string
import xml.etree.ElementTree as ET
from bs4 import BeautifulSoup
from time import sleep
import requests
import re
import os
from requests_toolbelt import MultipartEncoder
# 需要获取的两个数据
# <input type="hidden" name="formhash" value="30c6d8fa">
# <input type="hidden" name="hash" value="0a0d2c087fa9143d3c1eab8e3f3bc138">
# 服务器上传限制 *.rar;*.7z;*.zip;*.txt;*.jpg;*.png
class WuAiPojie:
# 初始化 ua:浏览器标识,cookie:登录cookie,fid:板块id
def __init__(self, ua, cookie, fid=2):
if len(ua) <= 0 | len(cookie) <= 0:
raise Exception("ua和cookie不能为空")
self.UA = ua
self.Cookie = cookie
self.fid = fid
self.FormHash = ""
self.Hash = ""
self.uid = ""
self.session = requests.session()
self.session.headers = {
"User-Agent": self.UA,
"Cookie": self.Cookie,
"Referer": "https://www.52pojie.cn/forum.php?mod=post&action=newthread&fid=2",
"Origin": "https://www.52pojie.cn",
"Accept": "*/*"
}
# self.session.verify = False
self.isInit = self.init()
def init(self):
try:
url = 'https://www.52pojie.cn/forum.php?mod=post&action=newthread&fid=' + str(self.fid)
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"
}
response = self.session.get(url, headers=headers)
self.FormHash = re.findall(r'<input type="hidden" name="formhash" value="(.*?)"[\s/]*>', response.text)
self.Hash = re.findall(r'<input type="hidden" name="hash" value="(.*?)"[\s/]*>', response.text)
self.uid = re.findall(r'<input type="hidden" name="uid" value="(.*?)"[\s/]*>', response.text)
if len(self.FormHash) | len(self.Hash) | len(self.uid) <= 0:
raise Exception("获取初始数据失败", response.text)
# print("初始化成功", self.FormHash, self.Hash, self.uid)
return True
except Exception as e:
raise Exception("获取初始数据失败", e)
def __init_check__(self):
if self.isInit is False:
raise Exception("请先初始化")
# 上传文件,返回 (附件id,文件名,插入到帖子的标签)
def upload(self, file, name=""):
self.__init_check__()
# 获取文件名和文件类型
_name, filetype, _type = self.__can_update__(file)
if len(name) <= 0:
name = _name
url = 'https://www.52pojie.cn/misc.php?mod=swfupload&action=swfupload&operation=upload&fid=' + str(self.fid)
multipart_encoder = MultipartEncoder(
fields={
'Filedata': (name, open(file, 'rb'), _type),
'Filename': (None, name),
'filetype': (None, filetype),
'formhash': (None, self.FormHash),
'uid': (None, self.uid),
'hash': (None, self.Hash),
},
boundary='-----------------------------' + ''.join()
)
response = self.session.post(url, data=multipart_encoder, headers={'Content-Type': multipart_encoder.content_type})
attach_id = response.text
prefix = "attach"
if filetype == ".jpg" or filetype == ".png":
prefix = "attachimg"
return attach_id, name, "[{0}]{1}[/{2}]".format(prefix, attach_id, prefix)
# 判断文件是否可以上传,并且返回文件类型和文件名
def __can_update__(self, file):
self.__init_check__()
if not os.path.exists(file):
raise Exception("文件[" + file + "]不存在")
file_type = os.path.splitext(file)
name = os.path.basename(file)
if file_type in [".rar", ".7z", ".zip", ".txt", ".jpg", ".png"]:
if file_type == ".zip":
_type = "application/x-zip-compressed"
elif file_type == ".png":
_type = "image/png"
elif file_type == ".jpg":
_type = "image/jpeg"
elif file_type == ".7z" or file_type == ".rar":
_type = "application/octet-stream"
else:
# elif file_type == ".txt":
_type = "text/plain"
return name, file_type, _type
else:
raise Exception("文件[" + file + "]类型不支持")
# 删除附件aid: [附件id_1,附件id_2...]返回删除数量
def delete(self, aid):
self.__init_check__()
# 经测试,多文件一起删会导致所有文件都没了
# url = 'https://www.52pojie.cn/forum.php?mod=ajax&action=deleteattach&inajax=yes&formhash=' + self.FormHash + '&tid=0&pid=0&aids[]=' + '&aids[]='.join(aid)
num = 0
for a in aid:
# 错误重试3次
for i in range(3):
try:
url = 'https://www.52pojie.cn/forum.php?mod=ajax&action=deleteattach&inajax=yes&formhash=' + self.FormHash + '&tid=0&pid=0&aids[]=' + a
response = self.session.get(url)
tree = ET.fromstring(response.text)
if tree.text != "1":
raise Exception("删除附件[" + a + "]失败")
num += 1
break
except Exception as e:
print(e)
finally:
self.__delay__()
return num
# 获取新帖的所有附件 返回附件列表 [(文件名,附件id,是否是图片),...]
def getfiles(self):
self.__init_check__()
url = "https://www.52pojie.cn/forum.php?mod=ajax&action=attachlist&fid=2&inajax=1&ajaxtarget=attachlist"
response = self.session.get(url)
_list = []
# 取出html
tree = BeautifulSoup(ET.fromstring(response.text).text.split('<script'), 'html.parser')
# 找class为xi2的a标签,获取文本
for a in tree.find_all("a", class_='xi2'):
_list.append((a.text, a.get('id').replace("attachname", ""), bool(a.get('isimage'))))
return _list
# 上传文件夹下的所有文件 [(附件id,文件名,插入到帖子的标签),...]
def upload_folder(self, folder):
self.__init_check__()
rs = []
for file_name in os.listdir(folder):
# 错误重试3次
for i in range(3):
try:
_t = self.upload(os.path.join(folder, file_name))
rs.append(_t)
print(_t)
break
except Exception as e:
print(e)
finally:
self.__delay__()
return rs
# 接口有限流,慢慢来
@staticmethod
def __delay__():
sleep(1)
if __name__ == '__main__':
cookie = "填你自己的,记得到发帖的页面拿,切记使用抓包的cookie,不然会报错"
ua = "填你自己的"
# 初始化上传类
t = WuAiPojie(ua, cookie)
# 遍历当前 ./upload 目录下的文件上传
t.upload_folder(os.path.abspath('') + os.path.sep + ".." + os.path.sep + "assets")
# 删除多个附件
# print(t.delete(["2678878","2678872"]))
# 获取新帖的所有附件
print(t.getfiles())
```
***成功样例***
## GUI
环境`pip install PyQt5 pyqt5-tools`
界面如下,代码参看附件
依赖环境
pip install requests_toolbelt requests beautifulsoup4 Hmily 发表于 2024-2-29 17:38
没看懂,这和网页上有有什么区别?如果附件没有使用插入帖子,也会被定期清理的。
先把一堆文件传附件,然后把原文章的img全部替换上传后的
再开新帖,点击使用,把改完的文章贴进去
还是得把GUI整出来,写个img替换表达式,这两天加工一下 感谢分享
感谢分享 谢谢分享 没看懂,这和网页上有有什么区别?如果附件没有使用插入帖子,也会被定期清理的。 感谢分享 先复制保存 QAQ~QL 发表于 2024-2-29 17:41
先把一堆文件传附件,然后把原文章的img全部替换上传后的
再开新帖,点击使用,把改完的文章贴 ...
把你手动搞错的替换成?那这种工具太小众了可能。