news 2026/4/19 12:46:23

用python解放右手(七) 网页数据抓取-告别手动复制粘贴

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用python解放右手(七) 网页数据抓取-告别手动复制粘贴

网页数据抓取:告别手动复制粘贴

本文基于 Python 3.9+,涉及库:requestsBeautifulSoup4。阅读时间约 12 分钟。

安装依赖:pip install requests beautifulsoup4 lxml


老板的"竞品监控"任务

周五早上,老板把阿明叫进办公室。

“阿明啊,咱们的产品定价,你帮我盯着点竞品。”

“怎么盯?”

"这几个网站,"老板递过来一张纸条,上面写着 5 个网址,“每天看看他们的价格,记下来,有变动告诉我。”

阿明回到工位,打开第一个网站——某电商平台的竞品页面。价格藏在页面中间,周围是推荐商品、广告横幅、用户评价……

阿明选中价格,Ctrl+C,打开 Excel,Ctrl+V。再打开第二个网站,重复。

5 个网站搞完,20 分钟过去了。

"这每天要搞一次?"阿明看着纸条,眼前发黑。

更惨的是,第二周有个竞品改版了,价格位置变了,阿明没发现,报给老板的还是上周的价格。老板在会议上引用错误数据,当场被客户指出,脸色铁青。

会后,阿明被批:“价格都能看错?”

阿明委屈:“我在家带娃呢,手动复制难免出错……”

他找到老张:“张哥,网页上的数据,能自动抓吗?”

老张:“能。让 Python 每天去’看’网页,变了就告诉你。”


第一步:认识requests——Python 的"浏览器"

“阿明,你打开网页看价格,本质上是浏览器向服务器发了一个请求,服务器把页面内容发回来。”

"requests就是帮 Python 做这件事——模拟浏览器发请求,拿到网页内容

pipinstallrequests

最简示例:获取网页内容

importrequests# 发送 GET 请求(就像你在浏览器地址栏输入网址)url="https://quotes.toscrape.com/"response=requests.get(url)# 状态码 200 表示成功print(f"状态码:{response.status_code}")# 网页内容(HTML 字符串)print(response.text[:500])# 打印前 500 字符

运行结果:

状态码: 200 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Quotes to Scrape</title> ...

requests.get(url)就是’去这个网址,把内容拿回来’。”

“状态码200是成功,404是页面不存在,500是服务器挂了。”


第二步:认识BeautifulSoup——HTML 的"解剖刀"

“拿到 HTML 后,里面是一大堆标签,怎么找到我们要的价格?”

BeautifulSoup就像一把解剖刀——把 HTML 切开,让你按标签、按类名、按 ID 精准找到想要的内容。”

pipinstallbeautifulsoup4 lxml

lxml是解析器,比自带的html.parser更快。”

最简示例:提取名言

importrequestsfrombs4importBeautifulSoup url="https://quotes.toscrape.com/"response=requests.get(url)# 用 BeautifulSoup 解析 HTMLsoup=BeautifulSoup(response.text,"lxml")# 找到所有 class="text" 的 span 标签(名言内容)quotes=soup.find_all("span",class_="text")fori,quoteinenumerate(quotes[:5],1):print(f"{i}.{quote.get_text()}")

运行结果:

1. "The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking." 2. "It is our choices, Harry, that show what we truly are, far more than our abilities." 3. "There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle." ...

soup.find_all('span', class_='text')就是’找出所有<span class="text">的标签’。”

get_text()是提取标签里的纯文字,去掉 HTML 标签。”

阿明瞪眼:“这么精准?”

“对。网页是结构化的,每个元素都有标签、类名、ID,就像每个抽屉都有标签,你按标签找就行。”


第三步:实战——抓取竞品价格

“来,模拟一个真实的竞品价格抓取场景。”

假设我们要抓取的网页结构如下(这是示例,实际网页需要你自己看源码):

<divclass="product-item"><h3class="product-name">超级手机 Pro</h3><spanclass="price">¥4999</span><spanclass="stock">有货</span></div><divclass="product-item"><h3class="product-name">无线耳机 Max</h3><spanclass="price">¥1299</span><spanclass="stock">缺货</span></div>

阿明问:“我怎么知道网页的结构?”

"右键 → 检查(Inspect),或者按 F12。"老张演示,“看到没?鼠标悬停在元素上,网页上对应的部分会高亮。”

“找到价格所在的标签和类名,然后写代码:”

importrequestsfrombs4importBeautifulSoupimportpandasaspdfromdatetimeimportdatetime# 目标网址(示例)urls=["https://example-shop.com/product-a","https://example-shop.com/product-b","https://example-shop.com/product-c",]results=[]forurlinurls:print(f"🔍 正在抓取:{url}")try:# 发送请求(加 Header,模拟真实浏览器)headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}response=requests.get(url,headers=headers,timeout=10)response.raise_for_status()# 如果状态码不是 200,抛出异常# 解析 HTMLsoup=BeautifulSoup(response.text,"lxml")# 提取数据(根据实际网页结构调整选择器)name=soup.find("h3",class_="product-name").get_text(strip=True)price=soup.find("span",class_="price").get_text(strip=True)stock=soup.find("span",class_="stock").get_text(strip=True)results.append({"商品名称":name,"价格":price,"库存":stock,"抓取时间":datetime.now().strftime("%Y-%m-%d %H:%M:%S"),"来源网址":url,})print(f" ✅{name}:{price}")exceptExceptionase:print(f" ❌ 抓取失败:{e}")# 保存为 Exceldf=pd.DataFrame(results)df.to_excel(f"竞品价格_{datetime.now().strftime('%Y%m%d')}.xlsx",index=False)print(f"\n📊 抓取完成!共{len(results)}条数据,已保存到 Excel")

“这段代码的关键点:”

“1.headers:模拟浏览器身份,有些网站会拦截没有 User-Agent 的请求。”

“2.timeout=10:10 秒没响应就放弃,避免卡死。”

“3.raise_for_status():自动检查 HTTP 错误,不用自己写 if。”

“4.strip=True:去掉文字前后的空白和换行。”

“5.异常捕获:某个网页挂了,不影响其他网页继续抓取。”


第四步:进阶——CSS 选择器

findfind_all够用了,但如果网页结构复杂,用CSS 选择器更灵活。”

# 用 CSS 选择器定位元素# soup.select() 返回列表# 选择 class="product-item" 下的所有 spanitems=soup.select(".product-item span")# 选择 id="main" 下的第一个 h1title=soup.select_one("#main h1")# 选择包含特定文本的元素importre price_element=soup.find("span",text=re.compile(r"¥\d+"))

select用 CSS 选择器语法,前端开发的同学会很熟悉。.class是类名,#id是 ID,tag是标签名。”

select_one是只取第一个匹配的元素。”


第五步:做个有礼貌的爬虫

“阿明,抓取网页有个原则——别给人家服务器添堵。”

“你想象一下,如果你开的网店,有人每秒来你店里看 100 次价格,你的服务器会不会卡?”

“所以咱们要做个’有礼貌的爬虫’:”

importtimeimportrandomforurlinurls:# ... 抓取代码 ...# 每次请求后随机等待 1-3 秒sleep_time=random.uniform(1,3)print(f" 😴 休息{sleep_time:.1f}秒...")time.sleep(sleep_time)

random.uniform(1, 3)生成 1 到 3 之间的随机小数,让请求间隔不规律,更像真人。”

“另外,如果网站有robots.txt(比如https://example.com/robots.txt),先看看人家允不允许爬。”


踩坑提醒:网页抓取的坑

坑 1:网页是动态加载的

“现在很多网站用 JavaScript 动态加载内容——你打开requests.get拿到的 HTML,里面根本没有价格,因为价格是靠 JS 后来加载的。”

“怎么判断?右键查看网页源代码,如果里面没有你看到的价格,就是动态加载。”

"解决办法:

  • SeleniumPlaywright(模拟真实浏览器,能执行 JS)
  • 找 API 接口(按 F12 → Network → 看 XHR 请求,很多数据是从 API 返回的 JSON)"

坑 2:反爬机制

"网站发现你在爬它,可能会:

  • 封你的 IP
  • 返回验证码
  • 返回假数据

"应对:

  • 加请求头(User-Agent、Referer)
  • 用代理 IP 池
  • 控制请求频率
  • 处理 Cookie 和 Session"
# 使用 Session 保持登录状态(Cookie 会自动带过去)session=requests.Session()session.headers.update({"User-Agent":"..."})# 先登录login_data={"username":"xxx","password":"xxx"}session.post("https://example.com/login",data=login_data)# 再抓取(会自动带上登录后的 Cookie)response=session.get("https://example.com/data")

坑 3:编码问题

“有些网页编码不是 UTF-8,中文会乱码。”

response=requests.get(url)response.encoding=response.apparent_encoding# 自动检测编码print(response.text)

坑 4:网页结构变了

“网站改版,类名变了,你的代码就抓不到数据了。”

"解决办法:

  • 抓取前检查关键元素是否存在
  • 加异常处理,结构变了发告警通知你
  • 用多个选择器做 fallback"
# 尝试多种方式定位价格price_element=(soup.select_one(".price")orsoup.select_one("[data-price]")orsoup.find("span",text=re.compile(r"¥")))ifnotprice_element:print("⚠️ 网页结构可能变了,检查选择器!")

一句话总结

阿明把爬虫脚本部署到了服务器上,设置了每天早上 8 点自动运行(用上一篇学的schedule)。

第二天,他打开邮箱,看到竞品价格_20240122.xlsx,5 个竞品的价格整整齐齐。

老张路过,看了一眼:

“爬虫就像请了一个实习生,你告诉他’每天去这几个网站,把价格抄下来’。不同的是,实习生会累会请假,Python 不会——它唯一的缺点是太老实,有时候会被网站的’此路不通’牌子拦住。”


扩展思考

"网页抓取的用途远不止竞品价格:

  • 新闻监控:抓取行业新闻,每天早上自动汇总发邮件
  • 股票数据:抓取股价、财报数据,做分析
  • 天气/汇率:每天抓取,自动更新到报表
  • 招聘信息:监控目标公司的招聘动态
  • 社交媒体:监控品牌提及(注意合规)

“核心逻辑都一样:请求 → 解析 → 提取 → 存储。”


下集预告

下一篇,阿明要把抓取的数据可视化——老板要看图表,不是表格。老张教他matplotlibpyecharts,让数据自己说话。

记住:爬虫的关键不是’能抓到’,而是’抓得稳、抓得久’。控制频率、处理异常、监控变化,比抓取本身更重要。


你有没有手动复制网页数据的经历?是什么场景?欢迎在评论区吐槽。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 12:44:57

突发!Sora之父跑路了

点击下方卡片&#xff0c;关注“CVer”公众号AI/CV重磅干货&#xff0c;第一时间送达点击进入—>【顶会/顶刊】投稿交流群添加微信号&#xff1a;CVer2233&#xff0c;小助手拉你进群&#xff01;扫描下方二维码&#xff0c;加入CVer学术星球&#xff01;可以获得最新顶会/顶…

作者头像 李华
网站建设 2026/4/19 12:44:43

OmenSuperHub:彻底解锁惠普游戏本性能的终极解决方案

OmenSuperHub&#xff1a;彻底解锁惠普游戏本性能的终极解决方案 【免费下载链接】OmenSuperHub 使用 WMI BIOS控制性能和风扇速度&#xff0c;自动解除DB功耗限制。 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否厌倦了官方Omen Gaming Hub的臃肿和…

作者头像 李华
网站建设 2026/4/19 12:37:53

终极ESP32 Arduino开发指南:从零开始快速构建物联网项目

终极ESP32 Arduino开发指南&#xff1a;从零开始快速构建物联网项目 【免费下载链接】arduino-esp32 Arduino core for the ESP32 项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32 想要快速上手ESP32开发&#xff0c;却不知道从何开始&#xff1f;本教…

作者头像 李华
网站建设 2026/4/19 12:36:16

手把手教你用C++实现SM4国密算法:从原理到代码逐行解析

深入解析SM4国密算法的C实现&#xff1a;从理论到实战 在当今信息安全领域&#xff0c;分组密码算法扮演着至关重要的角色。作为我国自主设计的商用密码标准&#xff0c;SM4算法以其高效安全的特性广泛应用于金融、政务等多个关键领域。本文将带领读者从零开始&#xff0c;用C完…

作者头像 李华