import os.path import random import re import threading import time import requests from loguru import logger from sqlmodel import Session, select from .base import BaseReporter from ...config.config import AppCtx from ...models.report_urls import ReportUrlModel from ...utils.common import get_all_cookies, get_proxies, report_keywords, get_reporter_name, \ generate_random_phone_number, md5 from ...utils.gen_cookie import GenCookie from ...utils.ua import random_ua class SiteReporter(BaseReporter): def __init__(self): self.engine_name = "SITE_REPORTER" self.status = 1 self.ev = threading.Event() self.upload_pic_url = "https://help.baidu.com/api/mpic" self.report_url = "https://help.baidu.com/jubaosubmit" self.request = requests.session() self.headers = { "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", "User-Agent": random_ua(), "Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-US;q=0.7,zh-TW;q=0.6", "sec-ch-ua_wap": '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"', "sec-ch-ua_wap-mobile": "?0", "sec-ch-ua_wap-platform": '"Windows"', "Cookie": "", } self.database = AppCtx.g_db_engine self.all_cookies = get_all_cookies() self.proxies = get_proxies() self.token_pattern = r'name="submit_token" value="(.*?)"' def stop(self): # logger.debug(f"{self.engine_name} stop called.") self.status = 0 self.ev.set() logger.warning(f"{self.engine_name} 收到退出消息,等待当前任务完成后退出") def run(self): """实现 PC 端的举报逻辑""" with Session(self.database) as session: stmt = select(ReportUrlModel).where(ReportUrlModel.is_report_by_site == False).where(ReportUrlModel.has_evidence == True) rows: list[ReportUrlModel] = session.exec(stmt).all() logger.info(f"[{self.engine_name}] 共计 {len(rows)} 条需要举报") for row in rows: if not self.status: break # 生成举报需要的基础数据 surl = row.surl q = row.q domain = row.domain img_path = f"./imgs/{domain}/{md5(surl)}.png" if not os.path.exists(img_path): logger.warning(f"{surl} 的截图不存在!") continue # 生成 cookie cookie = random.choice(self.all_cookies) report_site_cookie = GenCookie.run(cookie) self.headers["Cookie"] = report_site_cookie self.headers["User-Agent"] = random_ua() logger.debug(f"设置 cookie 为:{report_site_cookie}") # 先上传图片 pic_filename = self.upload_pic(img_path) # 再举报 result = self.do_report(domain, q, pic_filename, surl) if result: row.is_report_by_site = True session.add(row) session.commit() # 等待5秒继续举报 self.ev.wait(5) def upload_pic(self, img_path: str): try: with open(img_path, "rb") as fp: files = {"pic": fp} response = self.request.post( self.upload_pic_url, headers=self.headers, files=files, proxies=self.proxies, allow_redirects=False, timeout=5 ) pic_filename = response.json()["filename"] return pic_filename except Exception as e: logger.error(f"上传举报图片失败,错误: {e}") return None def do_report(self, domain: str = "", keyword: str = "", filename: str = "", link: str = ""): try: # 先获取提交数据用的 token response = self.request.get( "https://help.baidu.com/jubao", headers=self.headers, proxies=self.proxies, allow_redirects=False, timeout=5, ) match = re.search(self.token_pattern, response.text) if match: token_value = match.group(1) logger.debug(f"成功获取 submit_token: {token_value}") else: logger.error("未找到匹配的 submit_token") return None # 组装提交数据 if len(keyword) > 50: keyword = f"site {domain} {random.choice(report_keywords())}" data = { "submit_token": token_value, "os_info": "Macintosh", "browser_info": f"chrome 1{random.randint(20, 34)}", "pid": "1", "type": "3", "realname": get_reporter_name(), "mobile": generate_random_phone_number(), "category_id": "3", "query": keyword, "title": domain, "links": f"{link}", "content": f"{link} 存在大量淫秽色情的收录搜索结果!!!", "pic[]": filename } # 提交请求 response = self.request.post( self.report_url, data=data, headers=self.headers, proxies=self.proxies, allow_redirects=False ) json_data = response.json() # logger.debug(f"response={json_data}") if json_data["errno"] == 0: logger.success(f"[{self.engine_name}]{link} 举报成功") return True if json_data["errno"] == 11: logger.success(f"[{self.engine_name}]{link} 已经举报过") return True logger.debug(f"{json_data=}") return False except Exception as e: logger.error(f"[{self.engine_name}] 举报错误:{e}") return False