API从入门到精通03:让网页和Python真正调用商品查询接口
从“输入耳机却仍返回手机”的故障出发,取得资料、运行本机商品服务,在Network核对实际请求,修复网页参数,再借助AI完成独立Python调用、405反馈修复与双关键词迁移验收。
API从入门到精通03:让网页和Python真正调用商品查询接口
输入“耳机”,页面却还是手机,究竟是后台没有商品,还是调用方没把新条件发出去? 这篇教程沿着一次真实请求查清问题,再用AI协助写一个独立Python客户端。 重点是把输入、实际请求、响应和业务预期逐项核对;可以借助AI写代码,也可以手写,验收标准相同。
本课提供固定的虚构商品与已有查询服务。服务端的查询实现不是本课要补写的任务;你将修复网页调用,并完成新的客户端需求。本文可独立跟做,不需要先找到某个视频按钮。
下载资料
- 下载第三集跟做起点(ZIP):文件名为
search-start-r06.zip,包含course,没有预放Python客户端答案。 - 教师参考(独立ZIP,完成自己的任务之后再看):单关键词、双关键词和网页修复参考,与学员起点分开。
- 第二集教程与环境准备:需要补Python、编辑器或原课程环境时,从这里继续。
先把起点ZIP保存在“下载”中。右键ZIP → 全部解压缩,选择“下载”中的一个新文件夹 API第三集-r06,再打开里面的 course。不要直接在压缩包里运行。 已经做过第二集时,只把新 search 文件夹复制到原 course;保留原 .venv 和 hello 等文件。已有同名 search 时不要覆盖未保存的练习,改用新解压的完整course并按下面的独立环境分支准备。
下载的是源码与文字资料,不是Python或VS Code安装包。打开ZIP后看见文件,不代表本机服务已经启动。下面先核对目录和解释器,再启动服务。
以下命令均从同时包含
.venv与search的course目录执行。PowerShell A运行商品服务,PowerShell B运行客户端;浏览器用于页面和接口测试。
第三集商品搜索:运行与跟做说明
本课目标:让页面和一个独立Python程序,按同一份接口约定正确查询商品,并核对结果。
一、拿到什么、放到哪里
资料中的 search-start-r06.zip 包含一个course目录。商品数据是固定虚构样本;搜索页保留请求关键词写死的故障。
做过第二集:解压新包,只把 course/search 复制到你原来的course中。不要覆盖原hello、welcome、goodbye或.venv;若已有search目录,先确认版本,使用独立副本避免覆盖练习。应看到:
course/
.venv/ 第二集已建立
hello/ 第二集原文件保留
requirements.txt
verification/
constraints-windows-20261018.txt
search/ 本次新增
__init__.py
search_app.py 已提供的商品查询服务
README.md
AI提示词.md
web/
index.html 已提供的搜索页面
app.js 本课定位和修复的调用代码
第三集完整步骤在 search/跟做说明.md,随search一起复制,原course的第二集README不覆盖。
如果Markdown文件双击打不开,右键选择打开方式、记事本阅读;也可以在已安装的VS Code中打开并预览。
search/client_search.py 在课堂AI协助环节新增;search/client_search_task.py 是独立任务新增。起点不预放任何客户端完成态。
第一次从本集加入:使用整个新course,在下面的独立环境分支准备.venv;无需先把第二集全部代码补写完。尚未安装VS Code时,也先按第二集完成编辑器准备,再打开本次course。Python阅读仍使用第二集教程与补课入口。
二、从文件夹打开终端A,启动服务
- 在资源管理器打开course,即上图同时包含.venv和search的位置。
- 点击文件夹顶部地址栏,输入
powershell,按回车。 - 依次执行以下命令,每行按回车;确认当前目录和解释器。窗口A后面持续运行服务。
Get-ChildItem
.\.venv\Scripts\python.exe --version
.\.venv\Scripts\python.exe -m pip show fastapi uvicorn httpx
.\.venv\Scripts\python.exe -m uvicorn search.search_app:app --host 127.0.0.1 --port 8006
本课保持商品服务运行,修改网页后保存并刷新页面,修改客户端后重新运行客户端。若之前按其它命令启动了自己的本课服务,先在那个A窗口按Ctrl+C并等退出,再执行这里的完整命令;仅修改说明文字不会改变运行中的进程。
看到 Application startup complete 和8006地址后保持A窗口打开。没有成功输出时先保留报错,不能直接进入浏览器步骤。8006若被占用,核对是否为你自己的本课服务;不要结束未知进程。
如果HTTPX等依赖缺少,用同一环境执行下面的依赖命令,等提示符返回并核对版本后再启动:
.\.venv\Scripts\python.exe -m pip install -r requirements.txt -c verification\constraints-windows-20261018.txt
独立新环境分支
当前目录必须是新解压的course。先查版本:
py -3.12 --version
若已确认可用3.12,并且此目录尚无.venv:
py -3.12 -m venv .venv
.\.venv\Scripts\python.exe --version
.\.venv\Scripts\python.exe -m pip install -r requirements.txt -c verification\constraints-windows-20261018.txt
.\.venv\Scripts\python.exe -m pip show fastapi uvicorn httpx
已有课程支持的3.11时,先用 py -3.11 --version 确认,创建命令对应改为 py -3.11 -m venv .venv。找不到py,或没有3.11/3.12时,先按第二集教程的Python安装与新旧管理器分支准备,再回到版本检查;使用自己电脑中已核对可用的解释器。已有.venv不要重建,先核对其解释器与依赖。
三、浏览器里打开的三个位置
| 用途 | 完整地址 | 操作 |
|---|---|---|
| 搜索页面 | http://127.0.0.1:8006/ | 浏览器顶部地址栏输入后回车 |
| 接口测试页 | http://127.0.0.1:8006/docs | 展开GET /api/products,Try it out,填q,Execute |
| 直接查询 | http://127.0.0.1:8006/api/products?q=耳机 | 地址栏输入后回车,查看JSON |
127.0.0.1 指当前这台电脑自己;这三个入口都依赖A窗口运行中的本地服务。搜索页的HTML和脚本由该服务提供,使用相对路径请求同一来源的API。不要双击index.html用file地址打开,也不要另开Live Server改变来源。
四、先复现,再找证据
- 搜索页填手机,点击搜索,等待完成。应该返回手机101、102。
- 再改成耳机,重新点击搜索并等待完成。起点仍返回手机,这是本课故障。
- 按F12(或Ctrl+Shift+I),选择Network/网络,筛选Fetch/XHR,清空记录。
- 重新查耳机,选中本次新出现的products请求;先在Headers/标头的General区域查看Request URL、Request Method和状态码,再切Payload/负载查看Query String Parameters中的q。这里是URL查询参数,不代表GET有请求正文。
- 核对本次实际请求仍带q=手机,再到Response/响应查看query=手机、count=2、items中的101、102。
- 新开标签进入完整/docs地址,按GET /api/products文字展开,点Try it out,q填耳机,点Execute;核对Request URL、HTTP200、query=耳机、ID201/202。
不要把旧请求选中后只修改输入框制造对照,也不要把页面打印的准备发送地址单独当成实际网络证据。
五、只改这一处调用参数
VS Code打开course,进入 search/web/app.js。找到:
url.searchParams.set("q", "手机");
改为:
url.searchParams.set("q", keyword);
这里的keyword来自本次输入的 .value.trim()。保存Ctrl+S,回搜索页刷新Ctrl+R,再重新填写并发送。修改的是浏览器脚本,保存后还要刷新页面并重新查询。
六、把接口约定写清楚
服务:http://127.0.0.1:8006
方法:GET
路径:/api/products 不带尾斜杠
查询参数:q,字符串,服务端收到的q在服务端去空白前长度1到30;去掉首尾空白后不能空
匹配规则:商品名称包含去空白后的关键词;本课使用casefold比较
响应:JSON对象
query:服务端处理的关键词
count:返回商品数量
items:商品对象数组,每个对象有整数id、字符串name、字符串category
合法但无匹配:HTTP200,count=0,items=[]
q缺失、空字符串、全空白、服务端收到的q超过30字符:HTTP422
本课商品目录:
| id | name | category |
|---|---|---|
| 101 | 星河手机 | 手机 |
| 102 | 轻巧手机 | 手机 |
| 201 | 蓝牙耳机 | 耳机 |
| 202 | 有线耳机 | 耳机 |
| 301 | 机械键盘 | 键盘 |
| 302 | 便携键盘 | 键盘 |
这些数据用于独立核对。客户端先strip并发送清理后的keyword。终端输入两侧空格加30个有效字符,实际发送30字符;直接给API发送未经清理的32字符则会被拒绝。这是不同阶段的值,不是同一请求的长度冲突。
客户端必须读取真实接口响应,不能把这张表写死成查询结果。匹配是名称包含,不是商品分类严格相等,也不是语义搜索。
七、完整AI提示词P1:写独立调用程序
下面是可复制的完整提示词。先由你选择已有且有权使用的AI工具;本课不要求购买新工具。真实生成结果可能不同,按约定检查。
打开已登录的聊天式AI助手,新建聊天,把下面完整提示词粘贴到消息输入框,再点击发送。AI在这里先生成代码;本机商品服务的实际调用发生在稍后保存并运行客户端时。
请帮我完成一个商品查询客户端,让我理解它如何调用已有接口。
环境:Windows,课程Python 3.11或3.12,当前工作目录是course。
解释器为course/.venv/Scripts/python.exe。已有HTTPX,课程约束版本为0.28.1。
同一台电脑的商品服务已经在http://127.0.0.1:8006运行。
我需要新增的文件是search/client_search.py。
请先输出完整代码和关键解释,不自行安装依赖、启动服务或修改其它文件。
接口约定:
GET http://127.0.0.1:8006/api/products
路径没有尾斜杠。查询参数名为q,字符串,1至30字符;去掉首尾空白后不能空。
客户端先去首尾空白,发送清理后的keyword;长度指实际传出的q,而不是未经处理的键盘输入。
服务按商品名称是否包含关键词查询,不等于分类严格相等或语义搜索。
成功响应是JSON对象:
{"query":"耳机","count":2,"items":[{"id":201,"name":"蓝牙耳机","category":"耳机"},{"id":202,"name":"有线耳机","category":"耳机"}]}
合法但无匹配时仍为200,count是0,items是空数组。
缺少q、q为空/全空白、q超过30字符时返回422。
程序要求:
1. 从终端提示用户输入关键词,去首尾空白。空或超过30字符时说明原因,不发送请求。
2. 用HTTPX的params传q,值来自本次输入;设置明确的网络超时,例如5.0。
3. 打印实际响应对应的请求方法、URL、HTTP状态。
4. 先检查HTTP状态,再解析JSON,随后读取并显示商品id、name、category及数量。
5. 检查query与本次输入一致;count与items数量一致;每条商品名称满足匹配规则,编号不重复。
6. 区分请求/连接异常、非成功HTTP状态、JSON解析或业务结构问题,失败时不得显示业务验证成功。
7. 不将示例商品硬编码成正常查询结果,不修改服务端,不读取本地商品表冒充HTTP调用。
已知独立验收样本:手机应为ID集合101/102,耳机应为201/202;火星咖啡机为空。
样本只供运行后核对,不是用来生成假的查询输出。用接口测试页核对两种调用的条件与结果是否一致;用事先给定的商品目录和预期ID集合核对完整性。
请解释:哪一行实际发送请求;params中的q和值各指什么;如何从JSON取商品;
哪些检查可以自动完成,哪些仍需要我对照独立样本。
给出从course目录运行的完整命令。
如果你没有实际运行,不要声称已经运行通过。
八、真实反馈提示词P2
AI首次生成可能通过,也可能失败;不预设概率。首次输出与实际错误均应保留,不故意制造“AI自然犯错”的过程。第十节会把受控方法错误完整反馈给真实AI并复验。
发现失败时,用本次实际证据替换方括号内容,不编造日志:
原需求与接口约定保持不变,请先定位差异,不要重写整个工程。
本次输入:[填本次关键词]
实际请求方法和URL:[从Network或HTTPX真实输出复制]
实际HTTP状态:[若根本未取得响应,明确写没有HTTP状态]
实际响应/报错:[复制本次原文]
预期结果:[按接口约定和独立样本填写]
独立对照:[例如/docs同参数的实际结果]
当前调用代码:[贴相关最小片段]
请说明输入在哪一步与实际请求/结果不一致,给最小修改及理由。
修改范围只限调用方;保留原服务与其它已通过功能。
再列出需要我实际重跑的验证,不能只以没有语法错误或HTTP200作为通过。
未运行的部分请明确标注。
九、保存与运行Python客户端
AI给出代码后,核对入口8006、GET、q、输入变量、真实响应和失败分支。VS Code在search下新建 client_search.py,保存。不要保存成 .py.txt。
A窗口保持服务;从同一个course用文件夹地址栏powershell另开B窗口,运行:
.\.venv\Scripts\python.exe .\search\client_search.py
出现关键词提示后输入手机并回车,核对URL、状态、query、ID集合。再运行同一条命令输入耳机核对。AI即使能直接写入文件,也要核对实际写入路径并运行验收。
HTTPX的 timeout=5.0 是连接、读取、写入、连接池等待等超时配置,不是整个程序的总时间上限。
十、方法试验、独立任务与停启
用受控405完整练习反馈修复
这是教师主动改错请求方法的试验,不声称AI刚生成的客户端自然犯错。正确的 search/client_search.py 始终保留。
- 在VS Code复制正确客户端为
search/client_search_method_probe.py,只把实际发送处的client.get改为client.post;结构不同则找等价调用行。保存。 - 从course的B窗口执行下面命令,输入手机。记录该次真实方法、完整URL、状态和响应原文。预期POST与405;未得到这些现象就保留实际现场,不填假日志。
.\.venv\Scripts\python.exe .\search\client_search_method_probe.py
- 回到已有AI聊天,用第八节P2填写本次证据和副本的最小相关代码,然后实际点击发送。写明原约定GET、目标手机ID101/102、修改范围仅该副本。服务端、数据、正常客户端均不改。
- 检查真实建议和差异:应纠正请求方法,不接受给后台新增POST、删报错检查或直接打印预期商品的绕过。若建议不合要求,附同次证据继续反馈。AI没有本机运行证据时不能把“已修好”当验收。
- 将审核过的最小修改用于副本、保存;再次运行,仍输入手机,核对该次GET、200和ID101/102;再运行输入耳机,核对201/202。这才构成修复后的同条件复验和另一条件回归。
- 将修改前片段、失败输出、实际AI建议、修改差异和两次修复后输出保存在
search/验收记录.md,副本也保留。后续任务使用正常客户端或新任务文件,不覆盖原工程。
若P1自然生成的候选已经出现真实失败,同样保留首轮输出并按P2修复;受控405的来源仍要明确,不能剪成AI自然犯错。
独立交付:一次输入两个词,分别查询
详见本文后面的《双关键词独立任务》。不要直接复制P1充当自己的新需求;可以参考接口卡,自行向AI说明两组输入、顺序请求、分组输出、空白/空结果/失败行为和验收。
在search新增 client_search_task.py。从course运行:
.\.venv\Scripts\python.exe .\search\client_search_task.py
按程序提示分别输入两组关键词并回车。先查键盘+蓝牙,第二次保留键盘改为机,再验证一组无匹配和一组空白。保存每组的实际请求和结果,并用固定目录先确定预期ID。所有练习与验收完成前,保持服务A运行。
完成验收和独立任务之后,再停止服务
| 情况 | 应检查什么 |
|---|---|
| 手机 | q=手机,200,query=手机,ID101/102,count=2 |
| 耳机 | q=耳机,200,query=耳机,ID201/202,count=2 |
| 蓝牙(独立任务) | q正确,200,ID集合201,count=1 |
| 机(独立任务) | q正确,200,ID集合101/102/201/202/301,count=5;机械键盘也包含机 |
| 火星咖啡机 | q正确,200,count=0、items=[],没有残留旧结果 |
| 空白输入 | 页面/客户端提示,没有新商品请求 |
直接GET ?q= | 另开标签先访问本服务首页以准备好记录面板,再打开Network、切All/全部、清空,地址栏输入完整空q地址并回车;选新文档请求核对422,不能与正常空结果混为一谈 |
| 在独立副本用POST同一路径 | 405,原GET客户端保留 |
完成本文后面的《双关键词独立任务》后,切到A窗口按一次Ctrl+C,等待退出日志和提示符。可以观察一次受控连接失败,然后用完整命令重启,再查一次证明恢复:
.\.venv\Scripts\python.exe -m uvicorn search.search_app:app --host 127.0.0.1 --port 8006
保持A窗口运行,在同目录B窗口重新运行:
.\.venv\Scripts\python.exe .\search\client_search.py
十一、短排障
| 现象 | 先核对 |
|---|---|
| 找不到.venv解释器 | 当前是否在原course;不要在search/web里执行根目录命令 |
| No module named search | course下是否有search/search_app.py和__init__.py;是否多套一层course |
| 修改后仍旧结果 | 改的是运行副本的app.js吗;保存并刷新页面了吗;Network中是否为本次新请求 |
| 无响应/连接失败 | A窗口是否运行、是否8006、实际错误是什么;保留报错,不把所有网络错误归为一种原因 |
| /docs白屏 | 先用直接API地址判断服务能否响应,再查看openapi.json及Network的JS/CSS加载、Console报错 |
| Python读不到JSON | 看实际HTTP状态、URL及响应正文;不要仅凭打印字符串认定响应是JSON |
| 看到307 | 检查接口与调用路径是否统一无尾斜杠;不要把重定向当作同一个实验条件 |
第二集文件与环境保留。本课没有连接真实电商或支付平台。
双关键词独立任务
业务需求
客服需要连续核对两类商品,不想每查一个词都重启程序。请借助你可使用的AI,新建search/client_search_task.py:一次运行分别接收两个关键词,顺序请求同一个商品接口,按第一组、第二组展示各自的处理关键词、商品数量与明细。
使用同一份课程Python环境和HTTPX。服务A保持运行,不改服务端、数据、网页和原search/client_search.py,不新增依赖。允许AI完成全部代码;需求由你组织,运行和验收由你完成。完整参考实现单独提供,先做自己的版本再查看。
需要你自己决定并说明的事
- 按接口卡填写方法、完整入口、q来自哪个输入、响应字段和输出要求;可以查课内资料,不要求凭记忆默写。
- 两次请求顺序执行,分别标明组别,不把第一组的结果留作第二组结果。
- 每组关键词先去首尾空白。空或超过30字符时说明该组未发送;继续处理另一组。
- 无匹配是正常空结果;区分HTTP非成功与未取得响应的请求/连接失败。JSON解析或业务校验未通过可以共用一类清楚的失败提示,保留实际错误原因,不报整项成功。失败的一组不阻止另一组按相同规则尝试。
- 每次实际收到响应后,显示对应的实际方法、URL、状态与数据。未取得响应时不伪造HTTP状态;接口返回的query/count/items仍需检查。
可以让AI解释设计和代码,但不要只让它把验收表里的答案打印出来。
亲自运行与验收
从course的B窗口运行,A窗口保持服务:
.\.venv\Scripts\python.exe .\search\client_search_task.py
- 先写预期再跑:按跟做卡固定商品目录,分别确定键盘、蓝牙、机的预期ID集合。不要从待验收程序的输出反推答案。
- 第一次按程序提示输入键盘、蓝牙。必须是一次运行收两个词,分别产生自己的请求与结果。
- 第二次保留第一组键盘,只把第二组换成机。检查两组没有串词、串响应,第二组的结果随条件变化。
- 再查一组自己选择的不存在商品和一组耳机。无匹配组显示空结果,耳机组仍正常。
- 再输入一组全空白和一组耳机。空白组说明未发送,另一组仍应请求并核对;这与“发送合法词却没有商品”不同。
- 对发生的真实失败使用P2:贴实际输入、请求或尚未发送的状态、实际错误、最小代码与预期,再审核修改并重跑。首次正确无需人为制造AI错误。课堂受控405另留修复前后记录即可。
接口测试页可交叉核对相同条件下的调用一致性;判断是否漏商品仍要对照事先给定的目录。两个调用方请求同一个后端,不能相互充当独立完整性答案。
提交物和通过条件
| 提交物 | 通过条件 |
|---|---|
| 自己写的业务需求提示词与实际AI回复 | 不只复制“帮我写代码”;包含两组输入、接口约定、输出、失败行为与验收 |
| search/client_search_task.py | 真正按两组输入调用HTTP接口,从响应取数据;不写死商品,不覆盖已通过工程 |
| search/验收记录.md | 每轮有输入、预先确定的ID集合、运行命令、每组实际URL/方法/状态或无响应说明、响应与对照结论 |
| 修复记录 | 如出现失败,保留原始证据、实际反馈、采纳差异和同条件复验;不能把教学预置错误说成AI自然犯错 |
| 简短解释 | 指出输入进入q、发送请求和解析响应的位置;说明AI做了什么、自己核对了什么 |
仅更换文件名、换关键词或反复运行原单词客户端,未满足这项新业务需求。手写和AI代写按同一套业务证据验收。
本任务不要求新增自动化测试框架;运行输出可复制到记事本或VS Code中的记录文件。涉及不同工具的登录和发送方式沿用课程已演示的真实入口。
先完成自己的记录,再阅读教程页单独提供的教师验收参考。教师演示和参考检查通过不代表学员已完成。
夏末