前36篇的程序再能干,也只在你自己的电脑里打转——读你硬盘上的CSV、写你硬盘上的Excel。可你想查的很多东西根本不在硬盘上:天气在气象网站上,汇率在银行网站上,新闻在新闻网站上。今天给程序接上”网线”,让它自己上网把数据拿回来。今天只引入一个新概念:
requests.get()——程序版的”打开浏览器、输入网址、按回车”
一、从一个每天都要干的重复活说起
先讲个你肯定干过的事:每天早上打开浏览器,输入”沈阳天气”,看一眼,关掉。或者月底查汇率:打开银行网站,找到汇率页面,一个数字一个数字抄进表格。
一天一次不算什么,但架不住”每天”。这正是咱们从第1篇就念叨的那类活儿:固定动作、有规律、纯手工——最该交给程序的活儿。
可是前36篇的程序干不了这事。你写个程序读CSV,CSV得先在你硬盘上;你写个程序分析Excel,Excel得先下载下来。“上网查”这一步,一直是你这个”人肉搬运工”在干。
今天的任务就一句话:把这个搬运工开除,让程序自己去网上拿数据。
你可能觉得”上网”是浏览器的专利。不是。浏览器只是个”看得见的搬运工”——你在地址栏敲网址按回车,它就替你去网站上把内容搬回来,还顺便把内容画得漂漂亮亮。咱们今天学的,就是把”敲网址按回车”这个动作写成代码。至于”画得漂亮”,那是浏览器的副业,程序不需要——程序只要拿到原始内容就行。
二、今天的新概念:requests.get()——程序版的”敲网址按回车”
先花两分钟搞懂”网址”到底是什么
你在浏览器地址栏敲 https://www.weather.com.cn/weather/101010100.shtml 按回车,到底发生了什么?
把它想成寄快递就通了:
https://www.weather.com.cn是收件地址——天气网站这台”大楼”- 后面那串
/weather/101010100.shtml是门牌号——大楼里的哪个房间 - 按回车 = 寄出一封请求信(行话叫 HTTP 请求),信上写着”我要这个房间里的内容”
- 网站收到信,把网页内容打包寄回来(行话叫 HTTP 响应)
浏览器收到包裹后负责”装修”(把 HTML 画成好看的页面)。咱们的程序不需要装修,收到包裹、拆开、拿走里面的货就行。
这封”信”有自己的一套规矩,叫 HTTP(HyperText Transfer Protocol,超文本传输协议——名字唬人,其实就是”网上寄快递的规矩”)。你以后跟AI聊”HTTP”,就理解成”网上寄收快递的那套规矩”,一点都不神秘。
三行代码,一次”上网”
Python 做这件事的标准工具叫 requests(英文原意就是”请求”,名字直白到家)。先装上它:
pip install requests
然后,完整的第一次”程序上网”:
import requests
# 寄出请求信:我要这个网址的内容
回应 = requests.get("https://www.baidu.com")
# 看看包裹里有什么
print(回应.status_code) # 网站的"回执编号":200 表示"收到了,货在信封里"
print(len(回应.text)) # 拿到的网页内容有多长(字符数)
print(回应.text[:200]) # 瞄一眼前200个字符
跑完你会看到 200,然后一大串以 开头的字符。没错,这就是百度首页的”素颜”——你在浏览器里看到的那个漂亮页面,就是浏览器拿这串字符画出来的。
就这一行 requests.get(...),顶掉了你”打开浏览器→输入网址→按回车→等待→看页面”整套手动动作。记住它今天就毕业:requests.get(网址) = “去这个网址把内容拿回来”。
三个最常用的”拆包裹”动作
拿回来的 回应 对象里,最常用的就是这三样(今天先把这三样用熟,够用了):
| 写法 | 意思 | 什么时候用 |
|---|
|——|——|———–|
回应.status_code |
网站的回执编号 | 先看它,判断”货到没到” |
|---|---|---|
回应.text |
网页的文字内容 | 要”读内容”的时候 |
回应.ok |
是不是”好收据”(True/False) | 懒得记编号时的快捷判断 |
status_code 那个数字是网站给你的回执,最常见的是这几种:
200——”收到了,货在信封里”(一切正常)404——”查无此人”(网址写错了,或者页面被删了)403——”不接待”(网站拒绝你进入)500——”我们这边仓库塌了”(网站自己出故障了)
疫苗先打一针:requests.get() 成功执行 ≠ 拿到了数据。它只保证”信寄出去了、有回音”,回音可能是”404 查无此人”。所以拿到回应先看 status_code,就像收快递先看”拒收退回”还是”签收成功”。
把”查天气”改成程序版(先看个雏形)
下面是完整可运行的雏形,用一个专门给程序员练手的网站(httpbin.org,收到什么请求就原样回给你什么,特别适合当”沙袋”):
import requests
def 拿网页内容(网址):
"""去指定网址把内容拿回来。拿不到就返回 None。"""
回应 = requests.get(网址, timeout=10) # timeout=10:最多等10秒,别傻等
if 回应.status_code == 200:
return 回应.text
else:
print(f"出师不利,网站回执编号:{回应.status_code}")
return None
内容 = 拿网页内容("https://httpbin.org/get")
if 内容:
print("拿到了!内容开头是:")
print(内容[:300])
注意两处细节,都是上过战场的人才会写上的:
timeout=10——不写它,如果网站卡住不回信,你的程序会无限期傻等,像打客服电话永远不挂断- 先检查状态码再用内容——”货到没到”和”货好不好”是两码事
网址里的问号:同一个网站,查不同的东西
看这两条网址,眼熟吗?
https://www.weather.com.cn/weather/101010100.shtml ← 北京天气
https://www.weather.com.cn/weather/101070101.shtml ← 沈阳天气
页面结构一模一样,只有结尾那串数字不同——网址本身就能”带问题”。还有一种更明显的写法,问号后面挂一串”参数”:
https://www.baidu.com/s?wd=python教程
问号 ? 后面的 wd=python教程 就是”我问的问题”:wd 是参数名(要搜什么),等号后面是参数值。同一个网站,换参数就换内容——这就是”查天气”能自动换城市、”查汇率”能自动换币种的秘密。
在 requests.get 里,你不用手工拼这串问号,把参数装进字典递给 params 就行(字典,第13篇的老朋友):
import requests
# 同一个网址模板,换参数换内容——httpbin 会把参数原样回显,特别适合练手
参数 = {"city": "沈阳", "days": "3"}
回应 = requests.get("https://httpbin.org/get", params=参数, timeout=10)
print(回应.status_code)
print(回应.text[:300]) # 看看它回显的 "args" 里是不是你传的两个参数
跑完你会发现回显里出现了 "city": "沈阳"——你问的问题,网站收到了。今天先到”会带参数提问”为止,怎么从回应里把答案精准抠出来(JSON 格式),下一篇的主角就是它。
三、跟AI说需求→读懂→改进:第一次”网络版”三步走
老规矩,这一节是本系列的保留节目。今天用它来做一个真实的小工具:查一个网页能不能正常打开(网站值守的迷你版)。
第一步:跟AI说需求
“我是编程初学者,正在学 requests.get()。帮我写个Python函数:输入一个网址,程序去访问它,如果回执是200就说’网页正常’,否则把回执编号打印出来。代码要完整可运行,加中文注释。”
AI大概率给你这样的代码:
import requests
def 检查网页(网址):
回应 = requests.get(网址, timeout=10)
if 回应.status_code == 200:
print(f"{网址} 网页正常")
else:
print(f"{网址} 出问题了,回执编号:{回应.status_code}")
检查网页("https://www.baidu.com")
第二步:读懂(逐行对照)
def 检查网页(网址)——函数,第7篇的老朋友,输入网址输出检查结果requests.get(网址, timeout=10)——今天的新概念,寄信+最多等10秒if 回应.status_code == 200——回执检查,第4篇的条件判断- f字符串打印——第2篇就会了
没有一个语法是你不认识的,唯一的”新面孔”只有 requests.get()。这就是”每篇只引入一个新概念”的好处。
第三步:改进(这是拉开差距的一步)
拿AI的代码直接跑,会发现两个问题,正好当今天的”坑点疫苗”:
坑1:网址根本打不开时,程序直接崩给你看。比如你断网了,或者把网址打成 htp://...,程序会抛出一大段红字 ConnectionError。在咱们的”跟AI说需求”哲学里,这叫”没按剧本演”——正常路径好好的,一出意外就崩。
改进的话这么说:
“断网或网址写错时程序会抛异常崩溃。请用 try/except 包起来,出错时打印’访问失败’和原因,不要让程序崩。”
坑2:只检查一次,看不出”是不是一直都正常”。网站偶尔抽风一下和真的挂了,是两回事。
改进的话:
“帮我加一个循环,同一个网址连续检查3次,每次间隔5秒,最后报告成功了几次。”
合起来的成品(完整可运行):
import requests
import time
def 检查网页(网址, 次数=3, 间隔秒=5):
"""连续检查一个网址几次,报告成功了几次。"""
成功次数 = 0
for 第几次 in range(1, 次数 + 1):
try:
回应 = requests.get(网址, timeout=10)
if 回应.status_code == 200:
print(f"第{第几次}次:正常")
成功次数 += 1
else:
print(f"第{第几次}次:回执编号 {回应.status_code}")
except requests.RequestException as 原因:
# 断网、网址写错、超时……全都归这里管
print(f"第{第几次}次:访问失败({原因})")
if 第几次 < 次数:
time.sleep(间隔秒) # 歇口气再查,别把人家网站查烦了
print(f"总共 {成功次数}/{次数} 次正常")
检查网页("https://www.baidu.com")
这个改进版多了一样今天没细讲的东西:try/except(异常处理)。不用慌,它的意思就一句话:”这块代码要是出岔子,别崩溃,跳到 except 这儿来,按我说的办。“具体细节后面有专门的课讲,今天照猫画虎能跑就行。
四、四个必踩的坑(先打疫苗)
坑1:装了库却说找不到。 ModuleNotFoundError: No module named 'requests'——十有八九是”你装的 Python”和”你跑代码的 Python”不是同一个。在终端里敲 pip install requests 装到了A处,结果编辑器用的是B处的 Python。疫苗:报错就改用 python -m pip install requests,指定用”跑代码的那个 Python”自己去装。
坑2:拿了回执就当拿到了货。 上面说过,requests.get() 不抛异常只说明”有回音”,404 也是回音。先看 status_code,再用 text,这个顺序错不得。
坑3:不写 timeout,程序假死。 网站不回信时,不写 timeout 的程序会永远等下去,你以为它在干活,其实它在发呆。疫苗:requests.get 永远带上 timeout=10,这是写给”未来倒霉的自己”的保险。
坑4:拿别人网站当自家后院。 写个循环每秒查人家网站100次,轻则被封IP,重则给对方服务器添堵——这是不地道的。疫苗:循环访问记得 time.sleep() 间隔几秒,正式爬数据之前看看人家网站的规矩(后面第47篇专门讲”爬虫礼仪”)。
另外提前说个小坑:拿到的 回应.text 里如果中文显示成乱码,多半是网站没说清自己用什么编码。第41篇爬虫实战时会专门收拾它,今天先认识一下”乱码了不是你的错”。
五、跟AI协作的正确姿势(网络版特供)
写网络代码,AI的盲区格外明显:它没在你现在的网络环境里跑过代码,所以它写的代码”理论上对”,但”你的网络、你要访问的网站”它一无所知。三条特供建议:
- 把真实网址给AI。别问”怎么请求一个网站”,要问”帮我 requests.get 这个网址 https://xxx.com/yyy,把里面的XXX提取出来”。网址越具体,代码越能直接用。
- 把完整报错贴回去。网络代码的报错最有信息量(
ConnectionError、Timeout、SSLError……),原样贴给AI,它基本能一眼定位。别自己转述”它崩了”。 - 让AI写”防崩版”。直接说”请加 try/except 和 timeout,出错不要崩,打印友好提示”。网络代码天生比本地代码脆弱——你管得住自己的代码,管不住人家的网站。
六、今日小练习
练习1:程序版”网址体检”。写一个函数,输入网址,输出”能打开(200)”或”打不开,回执编号是XXX”。
提示:requests.get(网址, timeout=10) 拿回执,if 回应.status_code == 200 分两路。试着分别拿 https://www.baidu.com 和一个故意写错的网址跑一跑,看看两种回执长什么样。
练习2:给函数加上”断网保护”。把练习1的函数用 try/except 包一层,断网时(可以试试把网址写成 htp://www.baidu.com 模拟敲错)程序不崩溃,打印”访问失败”。
提示:except requests.RequestException as 原因: 能接住所有网络故障,打印 原因 就能看到具体是哪种。
练习3(动脑题):想想你会拿它干什么。列三个”每天都要上网看一眼”的东西(天气、汇率、快递状态、油价、某个页面更新没……),挑一个最想要的,写下:①它的网址大概是什么 ②你想从页面上拿走哪个信息。
提示:这题不用写代码——但请认真做,因为下篇预告里,我们就要真的做第一个了。你现在写下的需求,就是下节课的”跟AI说需求”素材。
下篇预告
下一篇(第38篇):API调用 —— 网站的”官方点餐窗口”。今天你从网页上”看”数据,可网页是画给人看的,从里面抠数据又费劲又容易碎。很多网站其实留了个”官方窗口”(API):你递上一句正经请求,它直接把干干净净的数据(JSON)端给你——天气、汇率这类活儿,用API三行代码就能搞定。下一篇,咱们把”查天气”这件事做成真家伙。
发表回复