VirusTotal API v3 URL扫描:正确获取分析报告的实践指南

花韻仙語
发布: 2025-09-13 10:14:01
原创
404人浏览过

VirusTotal API v3 URL扫描:正确获取分析报告的实践指南

针对VirusTotal API v3进行URL扫描时,许多开发者常混淆分析ID与URL资源ID,导致获取报告失败。本文详细阐述了如何正确使用API提交URL进行扫描,并利用返回的分析ID查询详细的扫描报告,避免常见的“Wrong URL id”错误,确保成功集成安全检测功能。

VirusTotal API v3 URL扫描流程概述

virustotal提供了一套强大的api,允许开发者自动化地提交文件、url等进行恶意软件检测,并获取详细的分析报告。对于url扫描,其api v3通常遵循两阶段模式:

  1. 提交URL进行分析: 通过特定的API端点提交一个URL,VirusTotal会将其加入扫描队列并开始分析。
  2. 查询分析结果: 在提交URL后,API会返回一个“分析ID”(analysis_id),开发者可以使用这个ID来查询分析任务的当前状态和最终报告。

理解两种关键的标识符至关重要:

  • 分析ID (Analysis ID): 这是提交URL(或其他实体)进行扫描后,VirusTotal为该次分析任务分配的唯一标识符。它的格式通常是 u-{hash}-{timestamp},例如 u-dbae2d0204aa489e234eb2f903a0127b17c712386428cab12b86c5f68aa75867-1701503514。
  • URL资源ID (URL Resource ID): 这是URL本身的唯一标识符,通常是该URL的Base64编码字符串。这个ID用于查询关于该URL资源本身的信息(例如,它以前的扫描历史或元数据),而不是特定分析任务的报告。

常见错误分析:混淆ID与API端点

许多开发者在初次使用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与获取分析报告

要正确地获取URL分析报告,关键在于使用正确的API端点:GET /analyses/{analysis_id}。

ViiTor实时翻译
ViiTor实时翻译

AI实时多语言翻译专家!强大的语音识别、AR翻译功能。

ViiTor实时翻译 116
查看详情 ViiTor实时翻译

步骤一:提交URL进行分析

通过 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
登录后复制

步骤二:获取URL分析报告

使用从上一步获取到的 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中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号