init commit
This commit is contained in:
commit
d5d5bf90fe
281
.gitignore
vendored
Normal file
281
.gitignore
vendored
Normal file
@ -0,0 +1,281 @@
|
||||
### VirtualEnv template
|
||||
# Virtualenv
|
||||
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
|
||||
.Python
|
||||
[Bb]in
|
||||
[Ii]nclude
|
||||
[Ll]ib
|
||||
[Ll]ib64
|
||||
[Ll]ocal
|
||||
[Ss]cripts
|
||||
pyvenv.cfg
|
||||
.venv
|
||||
pip-selfcheck.json
|
||||
|
||||
### Windows template
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
### Python template
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
### PyCharm+all template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
10
.idea/baidu-reporter.iml
generated
Normal file
10
.idea/baidu-reporter.iml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.12 (baidu-reporter)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/baidu-reporter.iml" filepath="$PROJECT_DIR$/.idea/baidu-reporter.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
1
app/__init__.py
Normal file
1
app/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .app import *
|
||||
123
app/app.py
Normal file
123
app/app.py
Normal file
@ -0,0 +1,123 @@
|
||||
import argparse
|
||||
import sys
|
||||
import os
|
||||
|
||||
from app.engines.reporter import Reporter
|
||||
|
||||
from .config import load_config, AppConfig
|
||||
from .models.base import connect_db, create_database
|
||||
|
||||
from loguru import logger
|
||||
import sqlalchemy.exc
|
||||
|
||||
|
||||
class MainApp:
|
||||
"""主应用"""
|
||||
|
||||
def __init__(self):
|
||||
self.args = None
|
||||
self.config: AppConfig = None
|
||||
self.db_engine = None
|
||||
|
||||
def parse_args(self):
|
||||
"""解析命令行参数"""
|
||||
parser = argparse.ArgumentParser(description="Baidu Reporter")
|
||||
|
||||
# 指定配置文件
|
||||
parser.add_argument(
|
||||
"-c",
|
||||
"--config",
|
||||
default="./config.local.toml",
|
||||
help="指定配置文件路径,默认为 ./config.local.toml",
|
||||
)
|
||||
|
||||
# 添加输入文件参数
|
||||
parser.add_argument(
|
||||
"-f",
|
||||
"--file",
|
||||
default="./urls.txt",
|
||||
help="指定输入文件路径,默认为 ./urls.txt",
|
||||
)
|
||||
|
||||
# 添加运行模式参数
|
||||
parser.add_argument(
|
||||
"-m",
|
||||
"--mode",
|
||||
help="指定运行模式:pc/site/wap,不指定则运行所有模式,多个模式使用英文逗号分隔",
|
||||
)
|
||||
|
||||
# 添加 web 服务器参数
|
||||
parser.add_argument(
|
||||
"--web", action="store_true", help="启动 web 服务器,启动后将忽略其他选项"
|
||||
)
|
||||
|
||||
# 如果没有传入任何参数,显示帮助信息
|
||||
if len(sys.argv) == 1:
|
||||
parser.print_help()
|
||||
sys.exit(0)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# 处理模式参数
|
||||
if args.mode:
|
||||
modes = [m.strip() for m in args.mode.split(",")]
|
||||
valid_modes = ["pc", "site", "wap"]
|
||||
invalid_modes = [m for m in modes if m not in valid_modes]
|
||||
if invalid_modes:
|
||||
parser.error(f'无效的运行模式: {", ".join(invalid_modes)}')
|
||||
args.mode = modes
|
||||
else:
|
||||
args.mode = ["pc", "site", "wap"]
|
||||
|
||||
# 检查输入的文件是否存在
|
||||
if not os.path.exists(args.file):
|
||||
parser.error(f"输入的文件不存在: {args.file}")
|
||||
|
||||
# 检查配置文件是否存在
|
||||
if not os.path.exists(args.config):
|
||||
parser.error(f"配置文件不存在: {args.config}")
|
||||
|
||||
self.args = args
|
||||
|
||||
def start_cli(self):
|
||||
"""开启 CLI 模式"""
|
||||
reporter = Reporter(self.args.file, self.args.mode, self.db_engine)
|
||||
reporter.run()
|
||||
|
||||
def start_web(self):
|
||||
"""开启 Web 模式"""
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
"""运行应用"""
|
||||
|
||||
# 解析命令行参数
|
||||
self.parse_args()
|
||||
|
||||
# 加载配置文件
|
||||
self.config = load_config(self.args.config)
|
||||
logger.info(f"加载配置文件 {self.args.config} 成功")
|
||||
|
||||
# 连接数据库
|
||||
try:
|
||||
self.db_engine = connect_db(self.config)
|
||||
logger.info(f"连接数据库 {self.config.database.database} 成功")
|
||||
except sqlalchemy.exc.OperationalError as e:
|
||||
# 如果错误类型是数据库不存在,询问用户是否执行初始化操作
|
||||
if "1049" in str(e):
|
||||
logger.info("数据库不存在,尝试初始化数据库")
|
||||
create_database(self.config)
|
||||
logger.info("数据库初始化成功,尝试连接数据库")
|
||||
self.db_engine = connect_db(self.config)
|
||||
logger.info(f"连接数据库 {self.config.database.database} 成功")
|
||||
else:
|
||||
logger.error(f"连接数据库失败,请检查配置文件或数据库服务是否正常: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
# 如果指定了 --web 参数,启动 web 服务器,忽略其他选项
|
||||
if self.args.web:
|
||||
logger.info("启动 Web 模式")
|
||||
return self.start_web()
|
||||
else:
|
||||
logger.info("启动 CLI 模式")
|
||||
return self.start_cli()
|
||||
1
app/config/__init__.py
Normal file
1
app/config/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .config import load_config, AppConfig, DatabaseConfig, ChromeConfig, gAppConfig
|
||||
47
app/config/config.py
Normal file
47
app/config/config.py
Normal file
@ -0,0 +1,47 @@
|
||||
from dataclasses import dataclass
|
||||
import toml
|
||||
|
||||
|
||||
@dataclass
|
||||
class DatabaseConfig:
|
||||
"""数据库配置"""
|
||||
|
||||
host: str
|
||||
port: int
|
||||
user: str
|
||||
password: str
|
||||
database: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class ChromeConfig:
|
||||
"""浏览器配置"""
|
||||
|
||||
proxy: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class AppConfig:
|
||||
"""总配置,如果未来增加 Web 服务,添加 WebConfig 即可"""
|
||||
|
||||
debug: bool
|
||||
database: DatabaseConfig
|
||||
chrome: ChromeConfig
|
||||
|
||||
|
||||
# 全局变量,存储配置信息,not best practice, but it's ok for now
|
||||
gAppConfig = AppConfig()
|
||||
|
||||
|
||||
def load_config(config_path: str) -> AppConfig:
|
||||
"""加载配置"""
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
config_dict = toml.load(f)
|
||||
|
||||
database_config = DatabaseConfig(**config_dict["database"])
|
||||
chrome_config = ChromeConfig(**config_dict["chrome"])
|
||||
|
||||
gAppConfig = AppConfig(
|
||||
debug=config_dict["debug"], database=database_config, chrome=chrome_config
|
||||
)
|
||||
return gAppConfig
|
||||
0
app/engines/__init__.py
Normal file
0
app/engines/__init__.py
Normal file
8
app/engines/collector.py
Normal file
8
app/engines/collector.py
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
class Collector:
|
||||
"""色站URL采集器,自动在百度翻页搜索,并保存搜索结果"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
7
app/engines/evidence.py
Normal file
7
app/engines/evidence.py
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
class EvidenceHolder:
|
||||
"""固定色站证据,搜索 URL 后截图,并生成举报链接存入数据库"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
72
app/engines/reporter.py
Normal file
72
app/engines/reporter.py
Normal file
@ -0,0 +1,72 @@
|
||||
from sqlalchemy import Engine, select
|
||||
from sqlmodel import Session
|
||||
|
||||
from app.utils.dp import DPEngine
|
||||
from .reporters.pc_reporter import PcReporter
|
||||
from .reporters.wap_reporter import WapReporter
|
||||
from .reporters.site_reporter import SiteReporter
|
||||
from ..models.report_urls import ReportUrlModel
|
||||
|
||||
from loguru import logger
|
||||
|
||||
|
||||
class Reporter:
|
||||
"""举报器,目前有三个渠道,以后可以继续扩展"""
|
||||
|
||||
def __init__(self, urls_file: str, mode: list[str], db_engine: Engine):
|
||||
self.urls_file = urls_file
|
||||
self.mode = mode
|
||||
self.db_engine = db_engine
|
||||
|
||||
# 初始化其他的 reporter
|
||||
self.reporters = {
|
||||
"pc": PcReporter(),
|
||||
"wap": WapReporter(),
|
||||
"site": SiteReporter(),
|
||||
}
|
||||
|
||||
# TODO 初始化 reporter 需要的公共数据,比如headless chrome等等
|
||||
# self.baseDP = DPEngine(is_wap=False, no_img=True)
|
||||
|
||||
def run(self):
|
||||
"""开始k站"""
|
||||
self.get_reports_data()
|
||||
|
||||
def get_reports_data(self):
|
||||
"""获取举报数据:页面截图,举报链接等,并存到数据库中"""
|
||||
|
||||
urls = self.read_urls()
|
||||
logger.info(f"从文件 {self.urls_file} 读取到 {len(urls)} 个 URL")
|
||||
|
||||
# 如果数据库中已经有了,就跳过
|
||||
# 如果数据库中没有,去获取页面截图、举报链接
|
||||
# 如果获取成功,就插入数据库
|
||||
# 如果获取失败,就记录日志
|
||||
dp = DPEngine(is_wap=False, no_img=True) # 用来截图的浏览器实例
|
||||
with Session(self.db_engine) as session:
|
||||
for url in urls:
|
||||
stmt = select(ReportUrlModel).where(ReportUrlModel.surl == url)
|
||||
report_url = session.exec(stmt).one_or_none()
|
||||
logger.debug(f"查询 {url} 的结果: {report_url}")
|
||||
if report_url:
|
||||
continue
|
||||
|
||||
# 获取页面截图、举报链接
|
||||
# 1. 打开baidu搜索URL,如果有结果就截一张图,没有的话就跳过
|
||||
# 2. 点击举报按钮,获取举报链接
|
||||
# 3. 打开 URL 截一张图
|
||||
# 4. 存到数据库里
|
||||
dp.browser.new_tab(url)
|
||||
|
||||
|
||||
def read_urls(self) -> list[str]:
|
||||
"""读取 urls 文件"""
|
||||
urls: list[str] = []
|
||||
with open(self.urls_file, "r") as fp:
|
||||
for url in fp:
|
||||
url = url.strip()
|
||||
if not url:
|
||||
continue
|
||||
urls.append(url)
|
||||
return urls
|
||||
|
||||
0
app/engines/reporters/__init__.py
Normal file
0
app/engines/reporters/__init__.py
Normal file
9
app/engines/reporters/base.py
Normal file
9
app/engines/reporters/base.py
Normal file
@ -0,0 +1,9 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
class BaseReporter(ABC):
|
||||
"""所有 reporter 的基类"""
|
||||
|
||||
@abstractmethod
|
||||
def run(self):
|
||||
"""运行 reporter,子类必须实现此方法"""
|
||||
pass
|
||||
11
app/engines/reporters/pc_reporter.py
Normal file
11
app/engines/reporters/pc_reporter.py
Normal file
@ -0,0 +1,11 @@
|
||||
from .base import BaseReporter
|
||||
|
||||
class PcReporter(BaseReporter):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
"""实现 PC 端的举报逻辑"""
|
||||
pass
|
||||
|
||||
|
||||
9
app/engines/reporters/site_reporter.py
Normal file
9
app/engines/reporters/site_reporter.py
Normal file
@ -0,0 +1,9 @@
|
||||
from .base import BaseReporter
|
||||
|
||||
class SiteReporter(BaseReporter):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
"""实现 PC 端的举报逻辑"""
|
||||
pass
|
||||
11
app/engines/reporters/wap_reporter.py
Normal file
11
app/engines/reporters/wap_reporter.py
Normal file
@ -0,0 +1,11 @@
|
||||
from .base import BaseReporter
|
||||
|
||||
class WapReporter(BaseReporter):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
"""实现 WAP 端的举报逻辑"""
|
||||
pass
|
||||
|
||||
|
||||
0
app/models/__init__.py
Normal file
0
app/models/__init__.py
Normal file
53
app/models/base.py
Normal file
53
app/models/base.py
Normal file
@ -0,0 +1,53 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import create_engine, event, text
|
||||
from sqlalchemy.dialects.mysql import BIGINT
|
||||
from sqlmodel import SQLModel, Field, Session
|
||||
from sqlalchemy.exc import OperationalError
|
||||
from loguru import logger
|
||||
|
||||
from ..config import AppConfig
|
||||
|
||||
|
||||
def get_timestamp():
|
||||
return int(datetime.now().timestamp())
|
||||
|
||||
|
||||
class BaseModel(SQLModel):
|
||||
"""数据库基类"""
|
||||
|
||||
id: int = Field(default=None, primary_key=True, sa_type=BIGINT(unsigned=True))
|
||||
created_at: int = Field(default=get_timestamp, sa_type=BIGINT(unsigned=True))
|
||||
updated_at: int = Field(default=get_timestamp, sa_type=BIGINT(unsigned=True))
|
||||
|
||||
|
||||
@event.listens_for(BaseModel, "before_update")
|
||||
def update_updated_at(mapper, connection, target):
|
||||
"""更新数据库记录的时候,自动更新 updated_at 字段"""
|
||||
target.updated_at = get_timestamp()
|
||||
|
||||
|
||||
|
||||
def connect_db(config: AppConfig):
|
||||
"""连接数据库"""
|
||||
|
||||
# 导入所有模型,为了自动创建数据表
|
||||
from .domain import DomainModel
|
||||
from .report_urls import ReportUrlModel
|
||||
|
||||
dsn = f"mysql+pymysql://{config.database.user}:{config.database.password}@{config.database.host}:{config.database.port}/{config.database.database}"
|
||||
engine = create_engine(dsn, echo=config.debug)
|
||||
|
||||
SQLModel.metadata.create_all(engine)
|
||||
|
||||
return engine
|
||||
|
||||
def create_database(config: AppConfig):
|
||||
"""如果数据库不存在,就调用这个函数初始化数据库"""
|
||||
|
||||
dsn = f"mysql+pymysql://{config.database.user}:{config.database.password}@{config.database.host}:{config.database.port}"
|
||||
engine = create_engine(dsn, echo=config.debug)
|
||||
|
||||
with engine.connect() as conn:
|
||||
conn.execute(text(f"CREATE DATABASE IF NOT EXISTS {config.database.database} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"))
|
||||
conn.commit()
|
||||
11
app/models/domain.py
Normal file
11
app/models/domain.py
Normal file
@ -0,0 +1,11 @@
|
||||
from sqlmodel import Field
|
||||
from sqlalchemy import VARCHAR
|
||||
|
||||
from .base import BaseModel
|
||||
|
||||
|
||||
class DomainModel(BaseModel, table=True):
|
||||
"""存储域名的模型"""
|
||||
|
||||
domain: str = Field(alias="domain", default="", sa_type=VARCHAR(1024))
|
||||
status: int = Field(alias="status", default=0)
|
||||
17
app/models/report_urls.py
Normal file
17
app/models/report_urls.py
Normal file
@ -0,0 +1,17 @@
|
||||
from sqlalchemy import VARCHAR
|
||||
from sqlmodel import Field
|
||||
|
||||
from .base import BaseModel
|
||||
|
||||
|
||||
class ReportUrlModel(BaseModel, table=True):
|
||||
"""存储举报 URL 的模型"""
|
||||
|
||||
domain: str = Field(alias="domain", default="", sa_type=VARCHAR(1024))
|
||||
surl: str = Field(alias="surl", default="", sa_type=VARCHAR(2048)) # 待举报的 URL
|
||||
token: str = Field(alias="token", default="", sa_type=VARCHAR(64))
|
||||
title: str = Field(alias="title", default="", sa_type=VARCHAR(1024))
|
||||
q: str = Field(alias="q", default="", sa_type=VARCHAR(1024)) # TODO: 这是干啥的?
|
||||
is_report_by_one: bool = Field(alias="is_report_by_one", default=False)
|
||||
is_report_by_site: bool = Field(alias="is_report_by_site", default=False)
|
||||
is_report_by_wap: bool = Field(alias="is_report_by_wap", default=False)
|
||||
0
app/repositories/__init__.py
Normal file
0
app/repositories/__init__.py
Normal file
0
app/utils/__init__.py
Normal file
0
app/utils/__init__.py
Normal file
154
app/utils/custom_base64.py
Normal file
154
app/utils/custom_base64.py
Normal file
@ -0,0 +1,154 @@
|
||||
import base64
|
||||
|
||||
from loguru import logger
|
||||
|
||||
|
||||
class CustomBase64:
|
||||
"""自定义的Base64编码和解码"""
|
||||
|
||||
mapping = {
|
||||
"Y": "V",
|
||||
"X": "U",
|
||||
"A": "Z",
|
||||
"s": "p",
|
||||
"J": "G",
|
||||
"F": "C",
|
||||
"U": "R",
|
||||
"u": "r",
|
||||
"W": "T",
|
||||
"i": "f",
|
||||
"V": "S",
|
||||
"E": "B",
|
||||
"2": "2",
|
||||
"P": "M",
|
||||
"C": "X",
|
||||
"8": "8",
|
||||
"r": "o",
|
||||
"L": "I",
|
||||
"H": "E",
|
||||
"M": "J",
|
||||
"j": "g",
|
||||
"b": "y",
|
||||
"p": "m",
|
||||
"O": "L",
|
||||
"l": "i",
|
||||
"R": "O",
|
||||
"G": "D",
|
||||
"I": "F",
|
||||
"y": "v",
|
||||
"t": "q",
|
||||
"0": "0",
|
||||
"c": "x",
|
||||
"Q": "N",
|
||||
"7": "7",
|
||||
"N": "K",
|
||||
"3": "3",
|
||||
"Z": "W",
|
||||
"n": "k",
|
||||
"1": "1",
|
||||
"d": "a",
|
||||
"5": "5",
|
||||
"S": "P",
|
||||
"K": "H",
|
||||
"h": "e",
|
||||
"k": "h",
|
||||
"w": "t",
|
||||
"T": "Q",
|
||||
"4": "4",
|
||||
"m": "j",
|
||||
"z": "w",
|
||||
"g": "d",
|
||||
"D": "A",
|
||||
"v": "s",
|
||||
"B": "Y",
|
||||
"/": "/",
|
||||
"q": "n",
|
||||
"f": "c",
|
||||
"a": "z",
|
||||
"9": "9",
|
||||
"o": "l",
|
||||
"e": "b",
|
||||
"x": "u",
|
||||
}
|
||||
reverse_mapping = {
|
||||
"V": "Y",
|
||||
"U": "X",
|
||||
"Z": "A",
|
||||
"p": "s",
|
||||
"G": "J",
|
||||
"C": "F",
|
||||
"R": "U",
|
||||
"r": "u",
|
||||
"T": "W",
|
||||
"f": "i",
|
||||
"S": "V",
|
||||
"B": "E",
|
||||
"2": "2",
|
||||
"M": "P",
|
||||
"X": "C",
|
||||
"8": "8",
|
||||
"o": "r",
|
||||
"I": "L",
|
||||
"E": "H",
|
||||
"J": "M",
|
||||
"g": "j",
|
||||
"y": "b",
|
||||
"m": "p",
|
||||
"L": "O",
|
||||
"i": "l",
|
||||
"O": "R",
|
||||
"D": "G",
|
||||
"F": "I",
|
||||
"v": "y",
|
||||
"q": "t",
|
||||
"0": "0",
|
||||
"x": "c",
|
||||
"N": "Q",
|
||||
"7": "7",
|
||||
"K": "N",
|
||||
"3": "3",
|
||||
"W": "Z",
|
||||
"k": "n",
|
||||
"1": "1",
|
||||
"a": "d",
|
||||
"5": "5",
|
||||
"P": "S",
|
||||
"H": "K",
|
||||
"e": "h",
|
||||
"h": "k",
|
||||
"t": "w",
|
||||
"Q": "T",
|
||||
"4": "4",
|
||||
"j": "m",
|
||||
"w": "z",
|
||||
"d": "g",
|
||||
"A": "D",
|
||||
"s": "v",
|
||||
"Y": "B",
|
||||
"/": "/",
|
||||
"n": "q",
|
||||
"c": "f",
|
||||
"z": "a",
|
||||
"9": "9",
|
||||
"l": "o",
|
||||
"b": "e",
|
||||
"u": "x",
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def decode(encoded):
|
||||
std_encoded = "".join(CustomBase64.reverse_mapping.get(c, c) for c in encoded)
|
||||
if not len(std_encoded) % 4 == 0:
|
||||
std_encoded = std_encoded + "=" * (4 - len(std_encoded) % 4)
|
||||
try:
|
||||
decoded = base64.b64decode(std_encoded).decode()
|
||||
return decoded
|
||||
except Exception as e:
|
||||
logger.error(f"解码错误: {e}")
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def encode(text):
|
||||
std_encoded = base64.b64encode(text.encode()).decode()
|
||||
custom_encoded = "".join(CustomBase64.mapping.get(c, c) for c in std_encoded)
|
||||
return custom_encoded.replace("=", "")
|
||||
23
app/utils/dp.py
Normal file
23
app/utils/dp.py
Normal file
@ -0,0 +1,23 @@
|
||||
from DrissionPage import Chromium, ChromiumOptions
|
||||
|
||||
from app.config import gAppConfig
|
||||
from app.utils import random_ua
|
||||
|
||||
class DPEngine:
|
||||
"""DrissionPage 引擎"""
|
||||
|
||||
def __init__(self, is_wap: bool = False, no_img: bool = True):
|
||||
chrome_opts = ChromiumOptions()
|
||||
chrome_opts.mute(True) # 静音
|
||||
chrome_opts.headless(True) # 无头模式
|
||||
chrome_opts.no_image(no_img) # 不加载图片
|
||||
chrome_opts.set_argument("--disable-gpu") # 禁用GPU
|
||||
chrome_opts.set_argument('--ignore-certificate-errors') # 忽略证书错误
|
||||
chrome_opts.set_argument('--start-maximized') # 最大化启动
|
||||
chrome_opts.set_argument(f'--user-agent={random_ua(is_wap)}') # 设置 UA
|
||||
# 设置代理
|
||||
if gAppConfig.chrome.proxy:
|
||||
chrome_opts.set_argument('--proxy-server', gAppConfig.chrome.proxy)
|
||||
|
||||
# 创建浏览器对象
|
||||
self.browser = Chromium(addr_or_opts=chrome_opts)
|
||||
259
app/utils/ua.py
Normal file
259
app/utils/ua.py
Normal file
@ -0,0 +1,259 @@
|
||||
import random
|
||||
import os
|
||||
import time
|
||||
|
||||
# 尝试使用/dev/urandom作为随机数种子,如果不可用则使用time.time()
|
||||
try:
|
||||
with open('/dev/urandom', 'rb') as f:
|
||||
random.seed(int.from_bytes(f.read(4), 'big'))
|
||||
except (FileNotFoundError, OSError):
|
||||
random.seed(int(time.time()))
|
||||
|
||||
WAP_UA = [
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Mobile/15E148 Safari/604.1",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
|
||||
"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G960F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/14.0 Chrome/87.0.4280.141 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 12; Pixel 6 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.74 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.1.0; Nexus 6P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 7.0; Nexus 5X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Mobile/15E148 Safari/604.1",
|
||||
"Mozilla/5.0 (Linux; Android 9; Redmi Note 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.152 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 12; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; Mi 11) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.0.0; ONEPLUS A5010) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-A715F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; P30 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-J730F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-N975U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 12_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1",
|
||||
"Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G950U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 7.1.2; Redmi Note 5A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 6.0.1; Galaxy J7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-A217F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-G960U1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.1.0; Redmi 6 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-M315F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 12; SM-G996U1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-A105F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A505FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.0 Mobile/14E5239e Safari/602.1",
|
||||
"Mozilla/5.0 (Linux; Android 12; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-M307FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G988B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A207F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-J600G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-J410F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A515F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-A715F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-J610F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.1.0; Redmi 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A105FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-A217M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-G965F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 12; SM-G998B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.1.0; Moto G6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-G950F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G960U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A305F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 7.0; SM-G610F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-J415FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-A526B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A205F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A405FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-G930F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.0.0; SM-G900F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; Redmi 7A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-A715FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.0.0; Moto G5 Plus) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A605FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-G960FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; Redmi Note 9) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G955F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.1; Nokia 5.1 Plus) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 12; SM-G991U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-A105FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-G780F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G960W) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A515FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.1.0; Moto G5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; Redmi Note 9 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A505G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 12; SM-A525F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-A605G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-N960F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G991N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A505U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 7.0; Moto G4 Plus) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.93 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-G973U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-G988N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-G770F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-A505F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-N975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-G973N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G781B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.1.0; Redmi 6A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 12; SM-A725F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A307FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-J415G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-A715GM) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.1.0; Moto G6 Play) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-A515W) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A705FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-G950N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-N986N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-A202F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 12; SM-G986B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-G965N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A405G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G770U1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-J810G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-M215F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.0.0; SM-G935F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; Mi A3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-J810Y) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-J730G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-A750F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G970F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-G988U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-M305F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G981U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-J600FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-J701F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.1.0; Redmi Note 6 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-G986U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-A405FM) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-J701M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 8.1.0; Pixel 2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 11; SM-N971N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-A305FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A217F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.93 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-A405FM) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-A202G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-J610FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 12; SM-G996B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 10; SM-N975U1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (Linux; Android 9; SM-G950U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36",
|
||||
]
|
||||
|
||||
PC_UA = [
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.137 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.92 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.77 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5414.74 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.124 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.87 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.61 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.102 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.81 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/82.0.4085.124 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_4_11) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_3_9) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.146 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_2_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_1_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/18.0.1025.168 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/17.0.963.83 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/11.0.696.77 Safari/537.36",
|
||||
]
|
||||
|
||||
def random_ua(is_wap: bool = False) -> str:
|
||||
"""获取 UA """
|
||||
if is_wap:
|
||||
return random.choice(WAP_UA)
|
||||
else:
|
||||
return random.choice(PC_UA)
|
||||
|
||||
12
config.local.toml
Normal file
12
config.local.toml
Normal file
@ -0,0 +1,12 @@
|
||||
debug = true
|
||||
|
||||
[database]
|
||||
host = "localhost"
|
||||
port = 3306
|
||||
user = "root"
|
||||
password = "123456"
|
||||
database = "baidu_reporter"
|
||||
|
||||
[chrome]
|
||||
proxy = "http://127.0.0.1:7890"
|
||||
browser_path = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"
|
||||
12
config.prod.toml
Normal file
12
config.prod.toml
Normal file
@ -0,0 +1,12 @@
|
||||
debug = false
|
||||
|
||||
[database]
|
||||
host = "localhost"
|
||||
port = 3306
|
||||
user = "root"
|
||||
password = "123456"
|
||||
database = "baidu_reporter"
|
||||
|
||||
[chrome]
|
||||
proxy = "http://127.0.0.1:7890"
|
||||
browser_path = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"
|
||||
18
main.py
Normal file
18
main.py
Normal file
@ -0,0 +1,18 @@
|
||||
from app import MainApp
|
||||
import sys
|
||||
|
||||
import traceback
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
app = MainApp()
|
||||
app.run()
|
||||
except Exception as e:
|
||||
print(f"程序运行失败,错误 {e} 信息如下:")
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
12
tests/test_custom_base64.py
Normal file
12
tests/test_custom_base64.py
Normal file
@ -0,0 +1,12 @@
|
||||
from app.utils import custom_base64
|
||||
from loguru import logger
|
||||
|
||||
raw = "hello! 你好!"
|
||||
|
||||
data = custom_base64.CustomBase64.encode(raw)
|
||||
logger.debug(data)
|
||||
|
||||
decodeData = custom_base64.CustomBase64.decode(data)
|
||||
logger.debug(decodeData)
|
||||
|
||||
assert decodeData == raw
|
||||
44
tests/test_dp.py
Normal file
44
tests/test_dp.py
Normal file
@ -0,0 +1,44 @@
|
||||
from DrissionPage import Chromium, ChromiumOptions
|
||||
|
||||
def md5_hash(text: str):
|
||||
"""计算文本的 MD5 哈希值"""
|
||||
import hashlib
|
||||
return hashlib.md5(text.encode()).hexdigest()
|
||||
|
||||
chrome_opts = ChromiumOptions()
|
||||
chrome_opts.mute(True) # 静音
|
||||
chrome_opts.no_imgs(False)
|
||||
chrome_opts.set_argument("--disable-gpu")
|
||||
chrome_opts.set_argument('--ignore-certificate-errors')
|
||||
chrome_opts.set_argument("--proxy-server=http://127.0.0.1:7890")
|
||||
chrome_opts.incognito(True)
|
||||
chrome_opts.set_browser_path(r"C:\Program Files\Google\Chrome\Application\chrome.exe")
|
||||
browser = Chromium(addr_or_opts=chrome_opts)
|
||||
|
||||
domain = "www.yunzhiju.net"
|
||||
keyword = "www.yunzhiju.net/zxysx/9850.html"
|
||||
|
||||
# tab = browser.new_tab(f"https://www.baidu.com/s?wd={keyword}")
|
||||
# tab = browser.new_tab(f"https://ip.im")
|
||||
|
||||
tab = browser.new_tab(f"https://www.baidu.com/s?wd={keyword}")
|
||||
|
||||
# tab.wait.eles_loaded('#timeRlt')
|
||||
# time_rtl_el = tab.ele('#timeRlt')
|
||||
# print(time_rtl_el.text)
|
||||
# time_rtl_el.click(by_js=True)
|
||||
|
||||
# tab.wait.eles_loaded("@class:time_pop_")
|
||||
# week_btn_el = tab.ele('t:li@@text()= 一月内 ')
|
||||
# week_btn_el.click(by_js=True)
|
||||
# tab.wait(2)
|
||||
|
||||
if "未找到相关结果" in tab.html:
|
||||
print("未找到相关结果")
|
||||
else:
|
||||
print("找到相关结果")
|
||||
img_path = f"./imgs/{domain}/{md5_hash(keyword)}.png"
|
||||
print(img_path)
|
||||
tab.get_screenshot(img_path)
|
||||
|
||||
|
||||
3
tests/test_logger.py
Normal file
3
tests/test_logger.py
Normal file
@ -0,0 +1,3 @@
|
||||
from loguru import logger
|
||||
|
||||
logger.debug("111")
|
||||
Loading…
x
Reference in New Issue
Block a user