0

0

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

花韻仙語

花韻仙語

发布时间:2025-09-13 10:14:01

|

430人浏览过

|

来源于php中文网

原创

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}。

稿定AI设计
稿定AI设计

AI自动去水印、背景消除、批量抠人像工具

下载

步骤一:提交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.

相关专题

更多
resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

152

2023.12.20

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

182

2023.12.04

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

284

2024.02.23

java标识符合集
java标识符合集

本专题整合了java标识符相关内容,想了解更多详细内容,请阅读下面的文章。

256

2025.06.11

c++标识符介绍
c++标识符介绍

本专题整合了c++标识符相关内容,阅读专题下面的文章了解更多详细内容。

122

2025.08.07

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

278

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1492

2023.10.24

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

25

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.5万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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