prompt-toolkit中如何转义API返回内容并保留自定义格式?
问题解决方案:YouTube搜索工具的HTML渲染与API限流问题
核心问题梳理
- API返回含特殊字符时,
print_formatted_text(HTML)触发"not well formed (invalid token)"错误 - 转义整个f-string会丢失自定义颜色与格式
- 拆分打印存在类型错误
- 需要控制API请求数量避免超限
解决方案
1. 安全转义动态内容,保留自定义HTML格式
不要转义整个字符串,只针对API返回的动态文本做HTML转义,自己写的格式标签(比如<color>)保持原样。用Python内置的html.escape()处理动态内容即可:
from html import escape from prompt_toolkit import print_formatted_text from prompt_toolkit.formatted_text import HTML # 示例:API返回带特殊字符的标题 api_title = "My <script> Test Playlist" # 仅转义动态内容,保留自定义颜色标签 formatted_html = f"<color='blue'>{escape(api_title)}</color> - <color='green'>[Playlist]</color>" print_formatted_text(HTML(formatted_html))
这样既解决了HTML解析错误,又不会丢失自定义的颜色和格式。
2. 拆分打印的类型错误修复
拆分打印时如果触发类型错误,要确保传入print_formatted_text的是合法的格式化文本类型(比如HTML对象或FormattedText),不要混合字符串和格式化对象。
错误示例(触发类型错误):
print_formatted_text("序号1: ", HTML("<color='red'>测试标题</color>"))
正确做法:把所有内容整合为一个HTML字符串,或者用FormattedText组合:
from prompt_toolkit.formatted_text import FormattedText # 用FormattedText组合不同样式的内容 formatted_content = FormattedText([ ("", "序号1: "), ("#ff0000", "测试标题"), ("", " - 播放列表") ]) print_formatted_text(formatted_content)
3. API请求数量限流控制
用计数器结合len()或直接计数的方式,限制最大请求次数,避免触发API限额:
MAX_REQUESTS = 10 request_count = 0 next_page_token = None while request_count < MAX_REQUESTS: # 发送API请求 response = youtube_search_api(query, page_token=next_page_token) request_count += 1 # 处理返回结果 for item in response.get("items", []): # 渲染逻辑 pass # 没有下一页则提前终止循环 next_page_token = response.get("nextPageToken") if not next_page_token: break
也可以把计数器封装成类或装饰器,让代码更整洁。
完整示例代码片段
from html import escape from prompt_toolkit import print_formatted_text from prompt_toolkit.formatted_text import HTML MAX_API_REQUESTS = 10 def render_result(item): # 转义API返回的动态字段 title = escape(item["snippet"]["title"]) channel = escape(item["snippet"]["channelTitle"]) item_type = "Playlist" if item["id"]["kind"] == "youtube#playlist" else "Video" # 拼接带格式的HTML内容 html_str = f""" <color='cyan'>{title}</color> <color='gray'> | 作者: {channel}</color> <color='green'> [{item_type}]</color> """ print_formatted_text(HTML(html_str)) def run_search(query): request_count = 0 next_page_token = None while request_count < MAX_API_REQUESTS: # 模拟API调用 api_response = call_youtube_api(query, page_token=next_page_token) request_count += 1 for item in api_response.get("items", []): render_result(item) next_page_token = api_response.get("nextPageToken") if not next_page_token: break
内容的提问来源于stack exchange,提问作者nannerpuss
相关产品推荐
相关产品推荐

