
virustotal提供了一套强大的api,允许开发者自动化地提交文件、url等进行恶意软件检测,并获取详细的分析报告。对于url扫描,其api v3通常遵循两阶段模式:
理解两种关键的标识符至关重要:
许多开发者在初次使用VirusTotal API v3时,会遇到一个常见的错误:在提交URL后获取到 analysis_id,但尝试使用 GET /urls/{id} 端点来查询分析报告。这会导致API返回 Wrong URL id 的错误信息。
让我们来看一个典型的错误代码示例:
import requests
def scanurl_incorrect(scan_url, api_key):
# 步骤一:提交URL进行分析
submit_url_endpoint = "https://www.virustotal.com/api/v3/urls"
payload = { "url": scan_url }
headers = {
"accept": "application/json",
"x-apikey": api_key,
}
response = requests.post(submit_url_endpoint, data=payload, headers=headers)
response.raise_for_status() # 检查HTTP错误
analysis_id = response.json().get('data', {}).get('id', '')
print(f"分析ID: {analysis_id}")
if not analysis_id:
print("未能获取分析ID。")
return
# 步骤二:尝试使用错误的端点获取报告
# 错误之处:这里应该使用 /analyses/{analysis_id},而不是 /urls/{analysis_id}
get_report_endpoint = "https://www.virustotal.com/api/v3/urls/" + analysis_id
headers = {
"accept": "application/json",
"x-apikey": api_key,
}
response = requests.get(get_report_endpoint, headers=headers)
print(response.text)
# 示例调用 (请替换为您的实际API Key)
# scanurl_incorrect("https://www.youtube.com/", "YOUR_VIRUSTOTAL_API_KEY")上述代码中,get_report_endpoint 被错误地构建为 https://www.virustotal.com/api/v3/urls/{analysis_id}。然而,GET /urls/{id} 端点期望的 id 是一个URL资源ID(通常是Base64编码的URL),而不是一个 analysis_id。因此,当传入 analysis_id 时,API会识别出这不是一个有效的URL资源ID,从而返回 BadRequestError 和 Wrong URL id 的错误。
要正确地获取URL分析报告,关键在于使用正确的API端点:GET /analyses/{analysis_id}。
通过 POST /urls 端点提交URL。成功后,响应会包含一个 data 对象,其中 id 字段就是我们需要的 analysis_id。
import requests
import json
import time
def submit_url_for_analysis(scan_url, api_key):
"""
提交URL到VirusTotal进行分析。
返回分析ID (analysis_id)。
"""
submit_url_endpoint = "https://www.virustotal.com/api/v3/urls"
payload = { "url": scan_url }
headers = {
"accept": "application/json",
"x-apikey": api_key,
}
try:
response = requests.post(submit_url_endpoint, data=payload, headers=headers)
response.raise_for_status() # 检查HTTP错误
response_data = response.json()
analysis_id = response_data.get('data', {}).get('id', '')
if analysis_id:
print(f"URL '{scan_url}' 已提交,分析ID: {analysis_id}")
return analysis_id
else:
print(f"提交URL失败,未能获取分析ID。响应: {response.text}")
return None
except requests.exceptions.RequestException as e:
print(f"提交URL时发生请求错误: {e}")
return None使用从上一步获取到的 analysis_id,通过 GET /analyses/{analysis_id} 端点查询分析报告。由于分析可能需要时间,通常需要进行轮询,直到报告状态变为“完成”(completed)。
def get_analysis_report(analysis_id, api_key, max_retries=10, delay=10):
"""
根据分析ID获取VirusTotal的URL分析报告。
会轮询直到分析完成或达到最大重试次数。
"""
if not analysis_id:
print("分析ID为空,无法获取报告。")
return None
report_endpoint_base = "https://www.virustotal.com/api/v3/analyses/"
headers = {
"accept": "application/json",
"x-apikey": api_key,
}
for i in range(max_retries):
try:
response = requests.get(f"{report_endpoint_base}{analysis_id}", headers=headers)
response.raise_for_status()
report_data = response.json()
status = report_data.get('data', {}).get('attributes', {}).get('status')
print(f"尝试 {i+1}/{max_retries} - 分析状态: {status}")
if status == 'completed':
return report_data
elif status == 'queued' or status == 'running':
time.sleep(delay) # 等待一段时间后重试
else:
print(f"未知或错误状态: {status}. 报告数据: {json.dumps(report_data, indent=2)}")
return None # 其他非预期状态
except requests.exceptions.RequestException as e:
print(f"获取分析报告时发生请求错误: {e}")
return None
except json.JSONDecodeError:
print(f"无法解析API响应为JSON: {response.text}")
return None
print(f"达到最大重试次数 ({max_retries}),分析未完成。")
return None将上述两个步骤整合到一个函数中,可以实现完整的URL扫描和报告获取流程:
import requests
import json
import time
def scan_url_and_get_report(scan_url, api_key, max_retries=10, delay=10):
"""
提交URL到VirusTotal进行分析,并轮询获取最终报告。
"""
# 步骤一:提交URL进行分析
submit_url_endpoint = "https://www.virustotal.com/api/v3/urls"
payload = { "url": scan_url }
headers = {
"accept": "application/json",
"x-apikey": api_key,
}
try:
response = requests.post(submit_url_endpoint, data=payload, headers=headers)
response.raise_for_status()
response_data = response.json()
analysis_id = response_data.get('data', {}).get('id', '')
if not analysis_id:
print(f"提交URL失败,未能获取分析ID。响应: {response.text}")
return None
print(f"URL '{scan_url}' 已提交,分析ID: {analysis_id}")
except requests.exceptions.RequestException as e:
print(f"提交URL时发生请求错误: {e}")
return None
except json.JSONDecodeError:
print(f"提交URL后无法解析API响应为JSON: {response.text}")
return None
# 步骤二:获取URL分析报告
report_endpoint_base = "https://www.virustotal.com/api/v3/analyses/"
headers = {
"accept": "application/json",
"x-apikey": api_key,
}
for i in range(max_retries):
try:
print(f"正在尝试获取报告 (第 {i+1}/{max_retries} 次尝试)...")
response = requests.get(f"{report_endpoint_base}{analysis_id}", headers=headers)
response.raise_for_status()
report_data = response.json()
status = report_data.get('data', {}).get('attributes', {}).get('status')
if status == 'completed':
print("分析完成,报告已获取。")
return report_data
elif status in ['queued', 'running']:
print(f"分析仍在进行中 (状态: {status}),等待 {delay} 秒后重试...")
time.sleep(delay)
else:
print(f"分析状态异常或未知: {status}. 报告数据: {json.dumps(report_data, indent=2)}")
return None
except requests.exceptions.RequestException as e:
print(f"获取分析报告时发生请求错误: {e}")
return None
except json.JSONDecodeError:
print(f"获取报告时无法解析API响应为JSON: {response.text}")
return None
print(f"达到最大重试次数 ({max_retries}),分析未完成或超时。")
return None
# --- 使用示例 ---
if __name__ == "__main__":
YOUR_API_KEY = "YOUR_VIRUSTOTAL_API_KEY" # <<<<<<< 请替换为您的VirusTotal API Key
TARGET_URL = "https://www.example.com/" # 替换为你想扫描的URL
if YOUR_API_KEY == "YOUR_VIRUSTOTAL_API_KEY":
print("请将 'YOUR_VIRUSTOTAL_API_KEY' 替换为您的实际API Key。")
else:
report = scan_url_and_get_report(TARGET_URL, YOUR_API_KEY)
if report:
print("\n--- 完整分析报告 ---")
print(json.dumps(report, indent=2))
# 提取关键信息,例如检测结果
last_analysis_stats = report.get('data', {}).get('attributes', {}).get('last_analysis_stats', {})
print(f"\n检测结果概览:")
print(f" 恶意: {last_analysis_stats.以上就是VirusTotal API v3 URL扫描:正确获取分析报告的实践指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号