0

0

VirusTotal API URL扫描结果获取:正确处理ID的关键

DDD

DDD

发布时间:2025-09-13 13:18:14

|

989人浏览过

|

来源于php中文网

原创

VirusTotal API URL扫描结果获取:正确处理ID的关键

本教程详细介绍了如何使用Python通过VirusTotal API进行URL扫描。文章重点阐述了在提交URL进行扫描后获取的分析ID与查询扫描结果所需的URL ID之间的区别与正确处理方法,旨在帮助用户避免常见的“Wrong URL id”错误,确保能准确检索到URL扫描报告。

1. VirusTotal API 简介与URL扫描流程

virustotal是一个免费的在线服务,用于分析可疑文件和url,以检测病毒、蠕虫、木马和其他类型的恶意软件。其api允许开发者集成virustotal的功能到自己的应用程序中,实现自动化扫描和报告检索。

使用VirusTotal API扫描URL通常包括两个主要步骤:

  1. 提交URL进行扫描: 向API发送一个POST请求,将待扫描的URL提交给VirusTotal。此操作会返回一个“分析ID”或“提交ID”。
  2. 获取扫描结果: 使用第一步中获得的特定ID,向API发送一个GET请求,以检索该URL的详细扫描报告。

在实际操作中,许多开发者在第二步获取扫描结果时会遇到Wrong URL id的错误,这通常是因为对ID的处理方式存在误解。

2. 提交URL进行扫描

首先,我们需要使用POST请求将URL提交给VirusTotal。以下是使用Python requests 库实现此操作的示例代码:

import requests
import json

def submit_url_for_scan(scan_url, api_key):
    """
    提交URL到VirusTotal进行扫描。
    :param scan_url: 待扫描的URL字符串。
    :param api_key: 您的VirusTotal API密钥。
    :return: 扫描任务的分析ID (analysis_id) 或 None。
    """
    url = "https://www.virustotal.com/api/v3/urls"
    payload = {"url": scan_url}
    headers = {
        "accept": "application/json",
        "x-apikey": api_key,
    }

    try:
        response = requests.post(url, data=payload, headers=headers)
        response.raise_for_status()  # 检查HTTP响应状态码,如果不是2xx则抛出异常
        response_json = response.json()

        # 从响应中提取分析ID
        analysis_id = response_json.get('data', {}).get('id')
        if analysis_id:
            print(f"成功提交URL: {scan_url},分析ID: {analysis_id}")
            return analysis_id
        else:
            print(f"提交URL失败或未获取到分析ID: {response_json}")
            return None
    except requests.exceptions.RequestException as e:
        print(f"提交URL时发生网络或HTTP错误: {e}")
        return None
    except json.JSONDecodeError:
        print(f"提交URL时响应内容不是有效的JSON: {response.text}")
        return None

# 示例调用 (请替换为您的实际API密钥)
# api_key = "YOUR_VIRUSTOTAL_API_KEY"
# analysis_id_example = submit_url_for_scan("https://www.youtube.com/", api_key)
# print(f"获得的分析ID: {analysis_id_example}")

执行上述代码后,如果成功,您将获得一个类似 u-dbae2d0204aa489e234eb2f903a0127b17c712386428cab12b86c5f68aa75867-1701503514 的字符串。这个字符串是VirusTotal为您的提交任务生成的“分析ID”或“提交ID”。

invideo AI
invideo AI

InVideo 使用现成的模板简化视频创建

下载

3. 正确获取URL扫描结果:ID处理的关键

许多用户会直接将上述获得的 analysis_id 用于查询URL扫描结果的GET请求,从而导致 Wrong URL id 错误。这是因为VirusTotal的URL分析结果查询API(/api/v3/urls/{id})所需的{id}并不是完整的分析ID,而是分析ID中的一个特定部分——通常是去除前缀和时间戳的哈希值部分。

问题根源: 提交URL后返回的分析ID格式通常是 u-{哈希值}-{时间戳}。例如:u-dbae2d0204aa489e234eb2f903a0127b17c712386428cab12b86c5f68aa75867-1701503514。 然而,用于查询具体URL报告的GET请求,其URL路径中的ID部分(即{id})需要的是中间的哈希值部分,而不是完整的分析ID。

解决方案: 我们需要从完整的分析ID中提取出中间的哈希值部分。一种简单有效的方法是使用字符串的 split('-') 方法,并取其第二个元素(索引为1)。

# 假设我们获得的分析ID是
full_analysis_id = 'u-dbae2d0204aa489e234eb2f903a0127b17c712386428cab12b86c5f68aa75867-1701503514'

# 正确提取用于查询的URL ID
url_id_for_query = full_analysis_id.split('-')[1] 
# 此时 url_id_for_query 将是 'dbae2d0204aa489e234eb2f903a0127b17c712386428cab12b86c5f68aa75867'

4. 完整的URL扫描与结果获取示例代码

结合上述提交和ID处理逻辑,以下是一个完整的Python函数,用于提交URL并获取其VirusTotal扫描报告:

import requests
import json
import time

def scan_and_get_url_report(scan_url, api_key, wait_time=10, max_retries=5):
    """
    提交URL到VirusTotal进行扫描,并获取其报告。
    :param scan_url: 待扫描的URL字符串。
    :param api_key: 您的VirusTotal API密钥。
    :param wait_time: 每次重试之间的等待时间(秒)。
    :param max_retries: 最大重试次数。
    :return: URL扫描报告的JSON数据,如果失败则为None。
    """
    # 1. 提交URL进行扫描
    submit_url = "https://www.virustotal.com/api/v3/urls"
    payload = {"url": scan_url}
    headers = {
        "accept": "application/json",
        "x-apikey": api_key,
    }

    print(f"正在提交URL '{scan_url}' 进行扫描...")
    try:
        post_response = requests.post(submit_url, data=payload, headers=headers)
        post_response.raise_for_status()
        post_response_json = post_response.json()

        full_analysis_id = post_response_json.get('data', {}).get('id')
        if not full_analysis_id:
            print(f"提交URL失败或未获取到分析ID: {post_response_json}")
            return None

        print(f"成功获取分析ID: {full_analysis_id}")

        # 2. 从分析ID中提取用于查询的URL ID
        # 格式通常为 u-{哈希值}-{时间戳}
        # 我们需要的是中间的哈希值部分
        try:
            url_id_for_query = full_analysis_id.split('-')[1]
            print(f"提取出用于查询的URL ID: {url_id_for_query}")
        except IndexError:
            print(f"无法从分析ID '{full_analysis_id}' 中正确提取URL ID。ID格式可能不符合预期。")
            return None

    except requests.exceptions.RequestException as e:
        print(f"提交URL时发生网络或HTTP错误: {e}")
        return None
    except json.JSONDecodeError:
        print(f"提交URL时响应内容不是有效的JSON: {post_response.text}")
        return None

    # 3. 循环查询扫描结果
    get_report_url = f"https://www.virustotal.com/api/v3/urls/{url_id_for_query}"

    for attempt in range(max_retries):
        print(f"尝试获取报告 (第 {attempt + 1}/{max_retries} 次)...")
        try:
            get_response = requests.get(get_report_url, headers=headers)
            get_response.raise_for_status()
            report_json = get_response.json()

            # 检查报告中是否存在错误,特别是BadRequestError
            if 'error' in report_json:
                error_message = report_json['error'].get('message', '未知错误')
                error_code = report_json['error'].get('code', '未知代码')
                print(f"获取报告时API返回错误: {error_code} - {error_message}")
                # 如果是 Wrong URL id 错误,通常是ID处理问题,但我们已经处理了
                # 可能是报告尚未生成,或URL本身的问题
                if error_code == "BadRequestError" and "Wrong URL id" in error_message:
                    print("尽管已尝试正确处理ID,但仍收到 'Wrong URL id' 错误。请检查原始分析ID是否有效或VirusTotal是否已处理此URL。")

                # 对于某些错误,可能需要重试,但对于Wrong URL id,重试意义不大
                # 对于报告未就绪的情况,可以继续等待
                if "Not found" in error_message or "still processing" in error_message.lower():
                    print(f"报告尚未就绪或正在处理中,等待 {wait_time} 秒后重试...")
                    time.sleep(wait_time)
                    continue # 继续下一次循环尝试
                else:
                    return None # 其他错误直接退出

            # 如果报告成功返回且没有错误,则返回报告
            print("成功获取URL扫描报告。")
            return report_json

        except requests.exceptions.RequestException as e:
            print(f"获取报告时发生网络或HTTP错误: {e}")
        except json.JSONDecodeError:
            print(f"获取报告时响应内容不是有效的JSON: {get_response.text}")

        print(f"等待 {wait_time} 秒后重试...")
        time.sleep(wait_time)

    print("达到最大重试次数,未能获取URL扫描报告。")
    return None

# --- 示例调用 ---
# 请替换为您的实际API密钥
VIRUSTOTAL_API_KEY = "YOUR_VIRUSTOTAL_API_KEY" 
TARGET_URL = "https://www.youtube.com/" # 替换为您想要扫描的URL

if VIRUSTOTAL_API_KEY == "YOUR_VIRUSTOTAL_API_KEY":
    print("请将 'YOUR_VIRUSTOTAL_API_KEY' 替换为您的实际VirusTotal API密钥。")
else:
    report = scan_and_get_url_report(TARGET_URL, VIRUSTOTAL_API_KEY)
    if report:
        # 打印部分报告内容,例如检测引擎数量
        print("\n--- 扫描报告摘要 ---")
        attributes = report.get('data', {}).get('attributes', {})
        last_analysis_stats = attributes.get('last_analysis_stats', {})
        print(f"URL: {TARGET_URL}")
        print(f"恶意检测数: {last_analysis_stats.get('malicious', 0)}")
        print(f"可疑检测数: {last_analysis_stats.get('suspicious', 0)}")
        print(f"无害检测数: {last_analysis_stats.get('harmless', 0)}")
        print(f"未检测数: {last_analysis_stats.get('undetected', 0)}")
        # print(json.dumps(report, indent=2)) # 打印完整报告
    else:
        print(f"未能获取 {TARGET_URL} 的扫描报告。")

5. 注意事项与最佳实践

  • API 密钥安全: 您的API密钥是敏感信息,请勿将其硬编码到公开的代码库中,或以不安全的方式共享。建议使用环境变量或配置文件来管理API密钥。
  • 错误处理: 在实际应用中,应更健壮地处理API请求可能出现的各种错误,例如网络问题、HTTP状态码非2xx、JSON解析失败、API限速等。示例代码中已包含基本的错误处理。
  • API 限速: VirusTotal API对请求频率有限制。免费公共API通常有较低的限速(例如每分钟4个请求)。如果您的应用需要进行大量扫描,可能需要购买私有API计划。在设计代码时,应考虑加入适当的延迟或重试机制来应对限速。
  • 报告延迟: 提交URL后,VirusTotal需要时间来完成扫描。立即查询报告可能会得到“正在处理中”或“未找到”的响应。因此,在获取报告时,通常需要一个循环等待和重试机制,直到报告可用。示例代码中的 wait_time 和 max_retries 参数就是为此目的。
  • 官方文档: 始终参考VirusTotal官方API文档(https://developers.virustotal.com/reference/overview)获取最新、最准确的信息。API的行为和ID格式可能会更新。

总结

通过本教程,我们深入探讨了使用Python与VirusTotal API进行URL扫描的关键步骤,特别是解决了在获取扫描结果时常见的Wrong URL id错误。核心在于理解VirusTotal返回的“分析ID”与查询报告所需的“URL ID”之间的差异,并学会通过字符串处理(split('-')[1])正确提取后者。遵循这些指导和最佳实践,开发者可以更有效地利用VirusTotal API,构建稳定可靠的恶意URL检测系统。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

422

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

536

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

313

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

77

2025.09.10

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

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

361

2023.08.03

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

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

212

2023.09.04

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

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

1503

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

625

2023.11.24

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

54

2026.01.31

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 3.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

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

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