Files
domainCheck/detect/baidu.py
2026-04-14 22:53:52 +08:00

263 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: UTF-8 -*-
'''
@Project :domainScanDemo
@File :baidu.py
@IDE :PyCharm
@Author :梦伴
@Date :2026/3/29 21:54
@explain : 百度域名检测工具 - 包含百度搜索结果查询和百度安全API检测功能
'''
import random # 随机数生成模块,用于随机选择浏览器类型
import re # 正则表达式模块用于从HTML中提取搜索结果
import time
from loguru import logger # 日志记录模块,用于记录程序运行日志
from curl_cffi import requests # curl_cffi库支持浏览器模拟的HTTP请求
from typing import List, Optional, Union, Any # 类型提示
def check_site(domain: str, sensitive_words: Optional[List[str]] = None, proxies: dict = None) -> Union[
None, tuple[bool, str], list[Any]]:
'''
通过百度搜索查询域名的相关信息
使用curl_cffi模拟浏览器访问百度搜索获取site:domain的搜索结果标题
:param domain: 待查询的域名www.baidu.com
:param proxies: 代理配置(如:{'http': 'http://127.0.0.1:7890', 'https': 'http://127.0.0.1:7890'}
:return: list - 搜索结果标题列表,如果查询失败则返回空列表
'''
# 初始化敏感词列表
if sensitive_words is None:
sensitive_words = []
# 添加重试机制
max_retries = 3
for retry in range(max_retries):
try: # try-except块用于捕获网络请求中的异常
# 构建搜索查询参数
# wd: 搜索关键词格式为site:域名
params = {
'wd': f'site:{domain}' # 搜索site:domain限制搜索结果为指定域名
}
cookies = {
'BIDUPSID': '053DBE4D820C6EFB729DC7B13B1F82B2',
'PSTM': '1775657119',
'H_PS_PSSID': '63148_67862_67986_68002_68142_68148_68152_68141_68165_68189_68226_68267_68296_68336_68369_68453_68438_68464_68541_68546_68558_68520_68589_68621_68615_68606_68601_68682_68671_68735_68544_68733_68766_68807_68901_68918_68836_68921_68955_68976_68997_69007_69010_69018_69024_69014',
'BAIDUID': '053DBE4D820C6EFB729DC7B13B1F82B2:FG=1',
'BDORZ': 'B490B5EBF6F3CD402E515D22BCDA1598',
'BAIDUID_BFESS': '053DBE4D820C6EFB729DC7B13B1F82B2:FG=1',
'BA_HECTOR': 'ah0l24210la4050l0g0k0g2g0h20071ktcocj27',
'ZFY': 'Qxyr75Xm7o8zUxYzuFnYoW7cnS:AnVp:BpnrNVkr3usno:C',
'delPer': '0',
'BAIDUID_REF': '053DBE4D820C6EFB729DC7B13B1F82B2:FG=1',
'H_WISE_SIDS': '110085_661771_667681_673676_683089_682564_685373_660925_687556_686285_690306_690303_690478_690576_690334_691545_685595_690883_692754_692777_692118_692910_693221_693364_693403_693656_693941_694124_693392_694171_694236_693996_694316_694324_693886_694409_694379_694696_694780_694783_692006_694884_694918_694996_694991_695032_695118_694840_695140_695193_695110_695262_688610_694933_695278_694865_695214_695374_690651_694577_692378_695452_695457_695480_695603_695642_695631_695668_695824_695843_695866_695888_695892_695897_695975_694177_695900_695939_696145_696150_696153_696069_696078_696066_694359_696288_696308_694985_696297_695715_696128_696313_696457_696431_696473_696492_696590_693385_696610_696682_696679_696662_696651_696655_696658_696673_696643_696110_696729_696733_696772_8000116_8000133_8000138_8000159_8000163_8000167_8000176_8000186_8000190_8000204',
'H_WISE_SIDS_BFESS': '110085_661771_667681_673676_683089_682564_685373_660925_687556_686285_690306_690303_690478_690576_690334_691545_685595_690883_692754_692777_692118_692910_693221_693364_693403_693656_693941_694124_693392_694171_694236_693996_694316_694324_693886_694409_694379_694696_694780_694783_692006_694884_694918_694996_694991_695032_695118_694840_695140_695193_695110_695262_688610_694933_695278_694865_695214_695374_690651_694577_692378_695452_695457_695480_695603_695642_695631_695668_695824_695843_695866_695888_695892_695897_695975_694177_695900_695939_696145_696150_696153_696069_696078_696066_694359_696288_696308_694985_696297_695715_696128_696313_696457_696431_696473_696492_696590_693385_696610_696682_696679_696662_696651_696655_696658_696673_696643_696110_696729_696733_696772_8000116_8000133_8000138_8000159_8000163_8000167_8000176_8000186_8000190_8000204',
'MSA_PBT': '147',
'MSA_ZOOM': '1000',
'wpr': '0',
'COOKIE_SESSION': '0_0_0_0_0_0_0_0_0_0_0_0_0_1775657396%7C1%230_0_0_0_0_0_0_0_1775657396%7C1',
'MSA_PHY_WH': '1440_3440',
'POLYFILL': '0',
'MSA_WH': '1254_940',
'kleck': '7ce2abac229d2e8ba435a8bcc6256f57f53e9d08954443bf',
'PSCBD': '16%3A1%3A3',
'SE_LAUNCH': '5%3A1775657396_16%3A29594323%3A3',
'BDSVRTM': '3',
'PSINO': '6',
'__bsi': '17976785662214065461_00_7_R_R_6_0303_c02f_Y',
}
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0',
'sec-ch-ua': '"Chromium";v="146", "Not-A.Brand";v="24", "Microsoft Edge";v="146"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
}
# 百度搜索URL
url = 'https://m.baidu.com/s'
# 发送GET请求获取搜索结果
# url: 请求URL
# params: 查询参数
# headers: HTTP请求头
# timeout=15: 超时时间15秒
# proxies: 代理配置
# impersonate: 模拟的浏览器类型
# .content: 获取响应内容(字节流)
# .decode('utf-8'): 解码为UTF-8字符串
response_text = requests.get(url, params=params, headers=headers, cookies=cookies, timeout=15,
proxies=proxies).content.decode('utf-8')
# 使用正则表达式提取搜索结果标题
# re.findall()返回所有匹配的结果列表
# 正则解释:匹配 <!--s-text--> 和 <!--/s-text--> 之间的内容
match = re.findall(r'<!--s-text-->([^<]+)<!--/s-text-->', response_text,re.S)
# 返回匹配结果列表,如果没有匹配则返回空列表
search_results= match if match else []
# 如果没有搜索结果,直接返回通过
if not search_results:
return True, ''
# 检查每个搜索结果是否包含敏感词
for result in search_results:
for sensitive_word in sensitive_words:
# 使用正则表达式检查是否包含敏感词
if re.search(sensitive_word, result, re.IGNORECASE):
logger.warning(f'检测到敏感词: {sensitive_word} 在结果: {result}')
return False, f'检测到敏感词: {sensitive_word} 在结果: {result}'
# 所有搜索结果都不包含敏感词,返回通过
return True, ''
except Exception as e: # 捕获所有异常
# logger.warning(f"百度site检测第{retry+1}次失败: {domain}, 错误: {e}")
if retry < max_retries - 1:
import time
time.sleep(2) # 等待2秒后重试
proxies=None
else:
# 达到最大重试次数,返回检测失败
logger.error(f"百度site检测失败: {domain}, 已达到最大重试次数")
return False, str(e) # 返回错误信息
def baidu(domain: str, proxies: dict = None) -> str:
'''
通过百度安全API检测域名安全状态
调用百度移动安全API检测域名是否为风险网站
:param domain: 待检测的域名www.baidu.com
:param proxies: 代理配置(如:{'http': 'http://127.0.0.1:7890', 'https': 'http://127.0.0.1:7890'}
:return: str - 安全状态描述("风险网站提示""高危网站提示""正常"),如果检测失败则返回错误信息
'''
# 构建HTTP请求头
headers = {
'Cache-Control': 'no-cache', # 不使用缓存
'Content-Type': 'application/json; charset=utf-8', # 内容类型为JSON
'Host': 'mobsec-sec.baidu.com', # 目标主机
'User-Agent': 'okhttp/3.12.12', # 模拟OKHttp客户端
}
# 构建请求参数
params = {
'auth_ver': '2', # 认证版本
'appkey': '4665fd2c6b0922a551e8ae74', # API应用密钥
'nonce': '1751309255340', # 随机数(注意:实际使用时应该动态生成)
'lc': '77qHTv4VtmRiXYtd', # 本地配置参数
'pkg': 'com.baidu.searchbox', # 应用包名
'vc': '-1', # 版本码
'cuid': 'CF0E6FCCD824D146605C16AC1C8BAC95%7CVFWAO56TC', # 设备ID注意实际使用时应该动态生成
'tk': '', # 令牌(空)
'type': '3', # 检测类型
'vn': '2.6.0', # 版本号
's': 'fdfef2ce96c1c7193f9b80425020f63e', # 签名(注意:实际使用时应该动态生成)
}
# 构建JSON请求数据
json_data = {
'url': f'https://{domain}/', # 待检测的URL添加https协议头
}
# 提取URL作为后续获取结果的键
key = json_data['url']
# 添加重试机制
max_retries = 3
for retry in range(max_retries):
try: # try-except块用于捕获API调用中的异常
# 发送POST请求到百度安全API
# url: API接口地址
# params: 查询参数
# headers: HTTP请求头
# json: JSON请求数据
# proxies: 代理配置
# .json(): 解析JSON响应
response = requests.post('https://mobsec-sec.baidu.com/3.1/scanurl', params=params, headers=headers,
json=json_data, proxies=proxies, timeout=15).json()
# # 记录API响应调试用
# logger.info(response)
# 安全状态码映射表
msgs = {
2193: '风险网站提示', # 风险网站
2243: '高危网站提示', # 高危网站
'_': '正常' # 默认正常
}
# 从响应中获取安全等级并映射为状态描述
# response['response']['datas'][key].get('grand_level', 'level'): 获取安全等级,默认值为'level'
# msgs.get(): 根据安全等级获取对应的状态描述,默认值为'正常'
return msgs.get(response['response']['datas'][key].get('grand_level', 'level'), '正常')
except Exception as e: # 捕获所有异常
logger.warning(f"百度网页安全中心检测第{retry+1}次失败: {domain}, 错误: {e}")
if retry < max_retries - 1:
time.sleep(2) # 等待2秒后重试
else:
# 达到最大重试次数,尝试不使用代理
if proxies:
logger.info('百度网页安全中心检测失败,尝试不使用代理')
try:
response = requests.post('https://mobsec-sec.baidu.com/3.1/scanurl', params=params, headers=headers,
json=json_data, proxies=None, timeout=15).json()
msgs = {
2193: '风险网站提示', # 风险网站
2243: '高危网站提示', # 高危网站
'_': '正常' # 默认正常
}
return msgs.get(response['response']['datas'][key].get('grand_level', 'level'), '正常')
except Exception as e2:
logger.error(f"不使用代理的百度网页安全中心检测也失败: {domain}, 错误: {e2}")
return str(e2) # 返回错误信息
return str(e) # 返回错误信息
# # ========================= 【测试代码】 =========================
# if __name__ == '__main__': # 程序入口,当直接运行此文件时执行以下代码
# # proxies = get_proxies()
# proxies = None
# # 测试用例1查询域名搜索结果
# logger.info("=== 测试百度搜索结果查询 ===")
# test_domain_1 = '920zl.com'
# logger.info(f"查询域名: {test_domain_1}")
#
# result_1 = check_site(test_domain_1, proxies=proxies)
# logger.info(result_1)
#
# # 测试用例3检测域名安全状态
# logger.info("=== 测试域名安全检测 ===")
# test_domain_3 = 'baidu.com'
# logger.info(f"检测域名: {test_domain_3}")
#
# result_3 = baidu(test_domain_3, proxies=proxies)
# logger.info(f"安全状态: {result_3}")
# logger.debug(proxies)
# domains = ['Lqyingye.com', 'tjjinLikeji.com', 'guokangLxs.com', 'zhuoyijz.com', 'jiandanrongyi.com', 'fromhhc.com',
# 'djxow.com', '725game.com', 'gcLpchd.cn', '6rdb.com.cn', 'sunmantech.com', 'hroxa.com', 'guLhu65.cn',
# 'xxjdch.com', '7e7fm1.cn', 'kaoxueb.com', 'jabas.cn', 'shzhongyi.com', 'figuangze.com', 'eztw9k.cn',
# 'foxok.com', 'oLLbmr.com', 'vwpwwkp.cn', 'cbmrs.com', 'zaozhuang56.com', 'hengxiangracing.com',
# 'jdyfbpq.cn', 'czca.cn', 'shibingxiongdi.com', 'ubxbm.cn', 'ydbaoshi.com', '2046hd.cn', 'mffmcp.com',
# 'hgLdhzz.com', 'okswmi.cn', 'caidaozg.com', 'dkdywx.cn', 'qkjps.com', 'Lwxgk.cn', 'drtechnoLogy.cn',
# 'akcie.cn', '588uu.com', 'kuaiyijian.net', 'c5b.cn', 'faka866.cn', 'wiraf03.cn', 'bobjibar.com',
# '166233.cn', 'adLfjcjq.cn', 'whrsom.com']
# for domain in domains:
# result_1 = check_site(domain)
# logger.info(f"搜索结果标题数: {len(result_1)}")
# for i, title in enumerate(result_1, 1):
# logger.info(f" 结果{i}: {title}")
# time.sleep(1)