json.loads(response.stdout)在Windows失效,Linux正常求解决
问题
在Windows系统运行Python代码时,执行json.loads(response.stdout)持续报错,但该代码在Linux系统可正常运行,经排查未找到原因,需兼容Linux和Windows的解决方案。
完整代码如下:
# -------------------Config------------------ archive_prefix = "output" output_txt_file = "output.txt" output_html_file = "index.html" archive_directory = "./archive" # You may enter a relative path (folder needs to start with ./) or you can use a specific path (C:\folder\folder2\) # Delete or rename old files based on the value of DeleteOldItems variable DeleteOldItems = False # If false, old items will be stacked in another location OutputHTML = True # Output as an HTML file so you can open it in a browser and click on the links HostHTML = False # If OutputHTML = True and HostHTML = True will host on all IPs on port 8080 (to reach if hosted on a personal computer, you can access using localhost:8080 as a URL in your web browser)) # ----------------End config----------------- import subprocess import json import os from datetime import datetime # Get the number of times to loop from user input num_loops = int(input("How many codes would you like?\n>> ")) index = 0 # Do not change print("") if DeleteOldItems: # Delete old files if they exist if os.path.exists(output_txt_file): os.remove(output_txt_file) if os.path.exists(output_html_file): os.remove(output_html_file) else: # Rename old files with timestamp if they exist timestamp = datetime.now().strftime("%Y%m%d%H%M%S") if os.path.exists(output_txt_file): new_txt_file = os.path.join(archive_directory, f"{archive_prefix}_{timestamp}.txt") os.makedirs(os.path.dirname(new_txt_file), exist_ok=True) os.rename(output_txt_file, new_txt_file) print(f"Old output stored as {archive_prefix}_{timestamp}.txt") if os.path.exists(output_html_file): new_html_file = os.path.join(archive_directory, f"{archive_prefix}_{timestamp}.html") os.makedirs(os.path.dirname(new_html_file), exist_ok=True) os.rename(output_html_file, new_html_file) print(f"Old output stored as {archive_prefix}_{timestamp}.html") # Initialize an empty list to store tokens tokens = [] # Loop the specified number of times for _ in range(num_loops): # Send the POST request using cURL curl_command = [ 'curl', 'https://api.discord.gx.games/v1/direct-fulfillment', '-H', 'authority: api.discord.gx.games', '-H', 'accept: */*', '-H', 'accept-language: en-US,en;q=0.9', '-H', 'content-type: application/json', '-H', 'origin: https://www.opera.com', '-H', 'referer: https://www.opera.com/', '-H', 'sec-ch-ua: "Opera GX";v="105", "Chromium";v="119", "Not?A_Brand";v="24"', '-H', 'sec-ch-ua-mobile: ?0', '-H', 'sec-ch-ua-platform: "Windows"', '-H', 'sec-fetch-dest: empty', '-H', 'sec-fetch-mode: cors', '-H', 'sec-fetch-site: cross-site', '-H', 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 OPR/105.0.0.0 (Edition std-1)', '--data-raw', '{"partnerUserId":"e518cd9e4d526d3de4aeb6d5e36f012bba82443ef1856a68029191ac8c6d136b"}', '--compressed' ] response = subprocess.run(curl_command, capture_output=True, text=True) # Parse the JSON response response_json = json.loads(response.stdout) # Get the token from the JSON response if it exists token = response_json.get("token") # Print the token if it exists if token: # Append the token to the text file URL = "https://discord.com/billing/partner-promotions/1180231712274387115" + token if OutputHTML == False: with open(output_txt_file, 'a') as f: f.write(URL + '\n\n') elif OutputHTML == True: index += 1 with open(output_html_file, 'a') as f: f.write(f"{index}. <a href=\"{URL}\">{token}</a><br>\n\n") # Append the token to the list tokens.append(token) print("please check for an output file") if OutputHTML == True & HostHTML == True: # Host the HTML file as a web server on IP 0.0.0.0 and port 8080 os.system(f"python -m http.server 8080 --bind 0.0.0.0")
原因分析
- curl跨平台行为差异:Windows默认未预装curl,手动安装后其输出格式、编码可能与Linux版本不同,比如输出带BOM的UTF-8文本或额外日志信息,导致
response.stdout不符合标准JSON格式。 - subprocess编码不匹配:
text=True在Windows下默认使用系统编码(如GBK),而API返回UTF-8编码内容,编码冲突会引发JSON解析失败。 - 命令执行失败:若curl不在Windows系统PATH中,
subprocess.run会执行失败,此时response.stdout为空或包含错误信息,无法解析为JSON。
解决方案
方案一:修复curl调用(兼容现有逻辑)
- 确保Windows安装curl:从curl官方渠道下载并添加到系统PATH,或使用绝对路径调用curl。
- 统一编码格式:将
subprocess.run的text=True替换为encoding='utf-8',强制使用UTF-8解析输出:response = subprocess.run(curl_command, capture_output=True, encoding='utf-8') - 添加错误处理:在解析JSON前校验请求状态和响应内容,避免无效输入导致报错:
if response.returncode != 0: print(f"curl执行错误: {response.stderr}") continue if not response.stdout.strip(): print("空响应,跳过解析") continue try: response_json = json.loads(response.stdout) except json.JSONDecodeError as e: print(f"JSON解析失败: {e}, 响应内容: {response.stdout}") continue
方案二:替换为requests库(推荐,完全跨平台)
使用Python原生requests库发送HTTP请求,彻底摆脱对系统curl的依赖:
- 先安装依赖:
pip install requests - 修改请求逻辑:
# 替换原有的subprocess和curl调用部分 import requests # Loop the specified number of times for _ in range(num_loops): # 构造请求头和数据 headers = { 'authority': 'api.discord.gx.games', 'accept': '*/*', 'accept-language': 'en-US,en;q=0.9', 'content-type': 'application/json', 'origin': 'https://www.opera.com', 'referer': 'https://www.opera.com/', 'sec-ch-ua': '"Opera GX";v="105", "Chromium";v="119", "Not?A_Brand";v="24"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'cross-site', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 OPR/105.0.0.0 (Edition std-1)', } data = '{"partnerUserId":"e518cd9e4d526d3de4aeb6d5e36f012bba82443ef1856a68029191ac8c6d136b"}' try: response = requests.post('https://api.discord.gx.games/v1/direct-fulfillment', headers=headers, data=data) response.raise_for_status() # 检查HTTP请求是否成功 response_json = response.json() except requests.exceptions.RequestException as e: print(f"请求失败: {e}") continue except json.JSONDecodeError as e: print(f"JSON解析失败: {e}") continue # 后续获取token的逻辑保持不变 token = response_json.get("token") # ... 剩余代码 ... - 修复逻辑错误:将最后一行的
OutputHTML == True & HostHTML == True改为OutputHTML and HostHTML(Python中逻辑与用and,&是位运算)。
额外优化
- 避免文件写入乱码:打开TXT/HTML文件时指定
encoding='utf-8':# TXT文件 with open(output_txt_file, 'a', encoding='utf-8') as f: f.write(URL + '\n\n') # HTML文件 with open(output_html_file, 'a', encoding='utf-8') as f: f.write(f"{index}. <a href=\"{URL}\">{token}</a><br>\n\n")
内容的提问来源于stack exchange,提问作者Gabrielzv1233
相关产品推荐
相关产品推荐

