拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Python爬虫入门:requests+BeautifulSoup实战最小闭环

很多人学 Python 爬虫不是被编程难度卡住的而是被“选择太多”卡住的。随便打开一份教程目录你能看到 requests、BeautifulSoup、lxml、Scrapy、Selenium、Playwright、正则、验证码处理、代理池……还没写出第一行代码人已经晕了。更常见的场景是你照着网上的代码复制下来跑起来却报错报错信息里全是英文你连该搜哪句话都不知道。所以这篇文章换一种方式。我不打算让你第一天就接触 Scrapy也不想让你背诵整套 HTTP 协议。我的目标很具体陪你跑通一个最小闭环——发请求、拿响应、解析数据、保存数据。当你能独立把一个网页里的标题、链接、正文抓下来并写进文件你对爬虫的恐惧感就会消失大半。后面再去学框架、分布式、数据清洗难度会直线下降。爬虫入门真正的门槛不是 Python 语法而是你对“一次 HTTP 请求”这件事的理解。这个认知一旦建立工具选择就不再纠结requests 负责拿数据BeautifulSoup 负责拆数据JSON/CSV 负责存数据。仅此而已。下面我们开始。1. 为什么很多新手学不懂爬虫先判断一个问题你学爬虫到底是为了什么我在很多技术社区看到零基础提问最常见的诉求有三种一是工作中需要采集公开数据做分析二是想给自己的小工具、公众号或网站补充内容三是单纯想找点有反馈感的编程练习。这三种需求都不需要你把爬虫架构搞得非常复杂。但很多教程的问题在于它们把“爬虫工程师”的知识体系直接塞给“想抓点数据”的新手。结果就是你被要求先学正则、再学 Scrapy、还要懂分布式部署最后还要会处理反爬。学了三个月好像都在学却答不出最基础的问题一个 requests.get 返回的 Response 对象里到底装着什么真正适合零基础的学习路径应该是一条有正反馈的路径。你写完一个文件运行能看到网页标题被提取出来哪怕只提取了一条这种反馈比背十个函数重要得多。从这个标准出发爬虫入门其实只需要四步发一个 HTTP 请求拿到网页源代码。学会在源代码里定位目标数据。把数据按固定格式保存下来。控制访问频率保证自己合法合规。这篇文章会按这个顺序展开。每一章都能独立运行每一章结束你都会有一个可复用的产出。先讲清楚原理再落到代码最后给排错清单和工程建议。2. 爬虫核心原理HTTP 请求与响应模型爬虫为什么会“爬起来”是因为它在模拟一个浏览器在服务器端发起请求。你在浏览器地址栏输入网址浏览器会把这个请求发给服务器服务器把 HTML 文本返回给你浏览器再把 HTML 解析成视觉效果。爬虫做的事就是跳过“解析成视觉效果”这一步直接拿走 HTML 文本从中抠出你要的数据。要理解这一步关键看四个概念。概念通俗解释说明URL资源地址告诉服务器你要访问哪个页面Request请求包含请求方式、请求头、请求体Response响应服务器返回的状态码、响应头、响应体HTML页面源代码半结构化的文本需要解析才能提取数据其中最常见的请求方式是 GET 和 POST。GET 一般用于获取数据参数写在 URL 里POST 一般用于提交数据参数写在请求体中。初学者不需要把 HTTP 协议背下来但需要知道服务端决定返回什么取决于你发出去的请求长什么样。如果你用爬虫访问服务端看到的请求里没有任何浏览器特征它就可能不给你正常的数据。这也是为什么很多新手遇到 403 错误。服务端识别出“你是一个程序不是一个浏览器”于是拒绝响应。解决办法不复杂通常只是加上一个常见的请求头 User-Agent告诉服务端你用的是某个浏览器版本。从这里往前推爬虫的最小闭环就是四条命令的逻辑发起请求 - 获取响应 - 解析数据 - 保存数据把四个环节拆开逐一实现入门阶段就没有理解盲区。3. 环境准备Python、pip 与开发工具3.1 安装 Python在动手写爬虫之前先把 Python 运行环境装好。这里以 Windows 为例但 macOS 和 Linux 的思路完全一致。到 Python 官网下载当前最新的稳定版安装包。注意建议选择 3.9 及以上版本不要下载还在测试阶段的 alpha/beta 版本新手排错成本太高。Windows 安装时有一个非常关键的勾选项Add Python to PATH。一定要勾上。如果忘记勾选后面在命令行执行 python 会提示“不是内部或外部命令”。安装完成后重新打开命令行窗口执行以下命令验证环境python --version pip --version如果输出类似这样的内容说明 Python 和 pip 都正常Python 3.12.4 pip 24.2 from C:\Python312\Lib\site-packages\pip (python 3.12)macOS 用户可以尝试python3 --version。Linux 多数发行版自带 Python但建议先确认版本太老的话考虑用系统包管理器安装新版本。3.2 配置 pip 镜像源pip 是 Python 的包管理工具安装第三方库靠它。如果你在国内网络环境直接执行 pip install 可能很慢建议先配置国内镜像源例如清华源或阿里源。这里给出清华源的配置方式pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple执行完成后以后安装第三方库的速度会明显提升。3.3 安装本文需要的依赖库本文只会用到三个库requests、beautifulsoup4、lxml。其中 lxml 是解析器BeautifulSoup 会使用它来解析 HTML。打开命令行执行pip install requests beautifulsoup4 lxml等待安装完成。然后执行一个验证命令确认库可以正常导入python -c import requests; from bs4 import BeautifulSoup; print(依赖安装成功)看到依赖安装成功就说明依赖环境已经就绪。3.4 选择编写代码的工具新手阶段不用在开发工具上纠结推荐两个方案想离代码更近使用 VS Code安装 Python 扩展插件即可。想开箱即用使用 PyCharm Community 版创建纯 Python 项目运行调试非常直观。无论选哪个新建项目后建议创建一个虚拟环境。在项目根目录执行python -m venv venvWindows 下激活虚拟环境venv\Scripts\activatemacOS / Linux 下使用source venv/bin/activate激活后再安装依赖库这样每个项目的依赖互相隔离不会污染全局环境。很多新手把各种库直接装进全局环境后面换项目时经常因为版本冲突头疼虚拟环境能规避掉其中大部分问题。4. 第一个闭环用 requests 获取网页内容4.1 构造最简单的请求在项目目录下新建crawler_demo.py先写一个最基础的 GET 请求。import requests url https://httpbin.org/get response requests.get(url) print(状态码:, response.status_code) print(响应文本:) print(response.text)运行这个文件python crawler_demo.py如果网络访问正常你会看到状态码200以及一段 JSON 格式的响应文本。httpbin 是一个公开的 HTTP 调试服务专门用来测试请求很适合学习阶段使用。如果你无法访问可以临时换成一个普通能访问的静态网页链接只要能返回 HTML 就满足演示目的。这一步的意义在于让你亲眼看懂一件事requests.get返回的 Response 对象里status_code表示服务器处理状态text存储着服务器返回的原始文本。抓网页本质上就是这样一次请求加一次响应。4.2 设置请求头与编码处理很多新手发现 requests 默认返回的网页中文是乱码原因是服务器返回的 HTML 里声明了charsetutf-8但 requests 可能没有正确识别。更稳妥的做法是手动指定编码。同时很多网站会对没有浏览器标识的请求直接拒绝。我们需要带上 User-Agent 请求头。import requests url https://httpbin.org/get headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 } response requests.get(url, headersheaders) response.encoding utf-8 print(状态码:, response.status_code) print(请求头中的 UA:, response.request.headers.get(User-Agent))这个改动虽然只加了几行但已经能解决很大一部分基础问题乱码问题、403 问题。后面进入实战时你会发现所有爬虫代码里几乎都会带上 headers 和 encoding 这两步。4.3 运行结果与验证运行上面的代码预期输出中能看到你手动指定的 UA 字符串。这是重要的一步验证说明服务端接收到的请求已经带有浏览器特征可以继续向下推进。如果这一步失败常见原因有两个网络不通连不上 httpbin.org可以换一个可访问的 URL 测试。没有安装 requests重新执行pip install requests。到这里最小闭环的第一步“发请求、拿响应”已经跑通。5. 第二个闭环用 BeautifulSoup 解析 HTML5.1 尽量别直接用正则解析新手最容易踩的坑是试图用正则表达式从 HTML 里匹配内容。HTML 结构千变万化标签属性顺序、空格、换行都会让脆弱的正则失效。BeautifulSoup 会把 HTML 解析成树形结构让你通过标签名、属性、层级关系找到目标节点。这才是解析页面的正确方式。5.2 用本地 HTML 文件练习解析直接抓真实网站页面结构复杂新手看不到解析过程。更稳妥的方式是先在本地构造一个简单 HTML 文件练熟解析逻辑后再换到真实页面。新建demo.html!DOCTYPE html html langzh-CN head meta charsetUTF-8 title文章列表/title /head body div classpost-item h2 classpost-titlea href/post/1.htmlPython 爬虫入门第一课/a/h2 span classdate2026-01-01/span /div div classpost-item h2 classpost-titlea href/post/2.htmlrequests 库从入门到进阶/a/h2 span classdate2026-01-02/span /div /body /html然后写解析脚本parse_demo.pyfrom bs4 import BeautifulSoup with open(demo.html, r, encodingutf-8) as f: html_content f.read() soup BeautifulSoup(html_content, lxml) post_items soup.find_all(div, class_post-item) for item in post_items: title_tag item.find(h2, class_post-title).find(a) title title_tag.get_text() href title_tag[href] date item.find(span, class_date).get_text() print(title, href, date)运行python parse_demo.py预期输出Python 爬虫入门第一课 /post/1.html 2026-01-01 requests 库从入门到进阶 /post/2.html 2026-01-02这里用到了 BeautifulSoup 最核心的三个动作find_all按条件查找所有符合条件的节点返回列表。find返回第一个匹配的节点。CSS 选择器你也可以用soup.select(.post-title a)达到同样效果写法与网页前端的 CSS 选择器一致容易上手。很多新人以为解析页面要背很多 API。其实频率最高的就这几个find、find_all、select、get_text、[属性名]。熟练掌握足够覆盖大部分静态网页场景。5.3 把请求与解析串联起来解析逻辑练熟后下一步就是把 requests 和 BeautifulSoup 串起来。下面的示例演示了“请求一个真实页面——解析链接——打印标题”的完整流程。因为不同网站的 HTML 结构差异很大这里的 CSS 选择器需要根据你实际访问的页面来调整。import requests from bs4 import BeautifulSoup url https://httpbin.org/html headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 } response requests.get(url, headersheaders, timeout10) response.encoding utf-8 soup BeautifulSoup(response.text, lxml) h1 soup.find(h1) if h1: print(页面标题:, h1.get_text())这段代码输出页面的 H1 标题。它演示的是爬虫最经典的套路请求 HTML解析内容。真实项目中你只需要把url换成目标页面地址把选择器换成目标数据的实际路径。到这里最小闭环的“解析数据”环节已经打通。6. 第三个闭环把数据保存到 JSON 与 CSV数据抓下来之后光打印在终端里是不够的。你需要把数据持久化才能做后续分析或展示。保存格式用 JSON 和 CSV 最合适一个更偏程序交换一个更偏表格查看。6.1 保存为 JSONJSON 格式和 Python 的字典列表结构非常接近。基于上一节解析出的数据直接构造列表并写入文件。import json posts [ {title: Python 爬虫入门第一课, href: /post/1.html, date: 2026-01-01}, {title: requests 库从入门到进阶, href: /post/2.html, date: 2026-01-02}, ] with open(posts.json, w, encodingutf-8) as f: json.dump(posts, f, ensure_asciiFalse, indent2) print(JSON 文件已生成)这里有两个细节需要留意ensure_asciiFalse保证中文以明文写入文件否则会变成一堆\uXXXX转义字符。indent2让 JSON 文件格式可读。运行后当前目录下会生成posts.json内容可以直接用文本编辑器或浏览器打开查看。6.2 保存为 CSVCSV 适合用 Excel 打开。如果你目标是把数据交给非技术同事CSV 远比 JSON 友好。import csv posts [ {title: Python 爬虫入门第一课, href: /post/1.html, date: 2026-01-01}, {title: requests 库从入门到进阶, href: /post/2.html, date: 2026-01-02}, ] with open(posts.csv, w, encodingutf-8-sig, newline) as f: fieldnames [title, href, date] writer csv.DictWriter(f, fieldnamesfieldnames) writer.writeheader() writer.writerows(posts) print(CSV 文件已生成)注意这里用的是utf-8-sig编码。如果写成utf-8生成的 CSV 用 Excel 打开很可能会出现中文乱码。utf-8-sig会在文件开头加上 BOM让 Excel 正确识别编码这是很实用的细节。顺带提一个新手很容易撞到的问题如果你尝试用 DataFrame 保存数据并把文件存成旧的.xls格式单表最大行数是 65536 行。数据量一旦超过这个数量就会报错或截断。更合理的做法是存成.xlsx格式或者直接用 CSV 保存原始数据需要时再分批导入 Excel。6.3 用 SQLite 做轻量存储扩展当数据量增长到几万条以上直接用文件保存已经不太方便查询。SQLite 是 Python 内置支持的轻量数据库不需要单独安装服务端适合当作爬虫数据的本地落点。import sqlite3 conn sqlite3.connect(posts.db) cursor conn.cursor() cursor.execute( CREATE TABLE IF NOT EXISTS posts ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, href TEXT NOT NULL, date TEXT ) ) posts [ (Python 爬虫入门第一课, /post/1.html, 2026-01-01), (requests 库从入门到进阶, /post/2.html, 2026-01-02), ] cursor.executemany(INSERT INTO posts (title, href, date) VALUES (?, ?, ?), posts) conn.commit() cursor.execute(SELECT * FROM posts) for row in cursor.fetchall(): print(row) conn.close()运行后当前目录会生成posts.db这是一个完整的数据库文件。SQLite 的细节不需要新手一次性掌握但至少要知道爬虫数据最终可以从“文件”升级到“数据库”查询、去重、增量更新都有更成熟的手段。到这里三个闭环全部跑通请求、解析、存储。你现在已经具备独立写一个静态网页爬虫的基础能力。7. 常见反爬机制与合规边界学完最小闭环后很多人会立刻跑到真实网站上尝试然后发现刚才这些代码好像不太管用了。这是正常现象。真实网站的页面背后往往存在各种反爬机制。常见的机制包括校验 User-Agent识别非浏览器请求。校验 Referer、Cookie 等请求头。检查访问频率单位时间内请求过多直接封禁。页面数据通过 JavaScript 动态加载HTML 里看不到目标数据。使用字体反爬、CSS 偏移、登录校验等方式干扰数据提取。面对这些机制新手阶段应该掌握的应对原则有三条第一尽量模拟正常浏览器的请求头。把常见请求头补齐例如 User-Agent、Accept、Accept-Language。很多 403 问题在补全请求头之后就能解决。第二控制请求频率。采集 100 页数据和采集 10 万页数据的策略完全不同。个人学习场景单次请求间隔 1 到 3 秒已经足够友好。用time.sleep(1)可以简单实现import time import requests urls [https://example.com/page/1, https://example.com/page/2] headers {User-Agent: Mozilla/5.0} for url in urls: response requests.get(url, headersheaders, timeout10) print(url, response.status_code) time.sleep(2)第三动态渲染页面不要急着上 Selenium。很多页面数据其实在接口里可以直接拿到只是你没发现。打开浏览器开发者工具切到 Network 面板刷新页面观察 XHR 请求往往能找到返回 JSON 数据的接口。直接请求接口比模拟浏览器渲染高效得多。关于合规边界这里需要明确一点爬虫可以采集公开数据但必须在合法授权范围内使用。访问网站前可以先查看对方网站的 robots.txt例如https://example.com/robots.txt里面通常会说明哪些路径允许抓取。个人学习时尽量控制频率不要对目标网站造成压力抓下来的数据不要用于商业用途不要涉及个人隐私、账号信息或受版权保护的内容。这些不是空洞的提醒而是爬虫开发者必须具备的基本素养。8. 常见问题与排查方法新手写爬虫报错几乎是必然的。重要的是有一套清晰的排查路径。下面整理了几个最高频的问题按“现象——原因——解法”的结构列出。问题现象可能原因排查方式解决方案SSL 证书报错目标网站证书链不完整或环境缺少证书看报错中是否出现SSLError字样更新证书或临时使用verifyFalse并同时设置urllib3.disable_warnings()返回 403服务端识别出非浏览器请求检查请求头中的 User-Agent补齐浏览器 UA 和其他常见请求头中文乱码响应编码识别错误查看网页源码中 charset 声明手动指定response.encoding utf-8或对应编码请求超时网络不稳定或目标网站响应慢确认是否能从浏览器正常打开设置timeout参数并实现重试机制解析结果为空选择器写错或节点是动态加载打印 response.text 检查目标数据是否存在调整选择器若数据不在 HTML 中改用接口请求或浏览器渲染方案访问频率过高被限流请求间隔太短查看响应码和响应头是否有限流标识增加 sleep 间隔控制并发数遵顚目标网站访问规范排查顺序建议固定下来先看状态码再看响应体最后才怀疑解析代码。很多同学一报错就怀疑 BeautifulSoup 写错实际上问题出在请求没拿到正确数据白调试半天。9. 最佳实践与工程建议当你能稳定爬取一个网站后就要开始考虑代码质量和可维护性。这里分享几个我在实际工程中认为最重要的建议。9.1 所有请求都要设置超时requests 默认不会超时如果目标网站迟迟不响应你的程序会一直卡住。每次请求必须带上 timeout 参数例如timeout10表示 10 秒内没有响应就主动放弃。这一步能避免整个爬虫任务被一个不可用的 URL 拖死。9.2 使用 Session 复用连接如果爬取的页面需要同一个会话用requests.Session()代替每次单独的requests.get。Session 会自动保持 Cookie也能复用底层连接减少握手次数。import requests session requests.Session() session.headers.update({ User-Agent: Mozilla/5.0 }) resp session.get(https://httpbin.org/cookies/set/name/value) print(resp.status_code)9.3 日志代替 print爬虫任务跑起来之后print 的输出在终端里一闪而过很难追溯。更规范的做法是用 Python 的 logging 模块把运行信息写入文件。import logging logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, filenamecrawler.log ) logging.info(开始抓取页面)9.4 数据去重与增量检查重复采集是爬虫项目里最常见的问题。每次入库前先检查数据是否已存在可以基于 URL 或内容哈希做去重。SQLite 里给 URL 字段添加唯一索引就是一个简单的去重方案。9.5 不要过早引入分布式很多新手一听到“分布式爬虫”就觉得是必经之路。实际上绝大多数学习项目和个人采集任务单机、单进程加上合理限速已经足够。分布式爬虫带来的成本很高包括节点管理、任务调度、数据汇总、反爬风险扩大。只有当单机采集速度确实成为瓶颈时再考虑 Scrapy 加分布式扩展。9.6 保持最小权限和合规意识爬虫涉及的数据采集要遵守网站规则和法律法规。不要在未授权的情况下绕过登录验证、破解验证码、采集非公开数据。个人学习以公开数据为主访问频率保持克制。把爬虫当成一种普通的数据获取工具而不是漏洞利用手段。10. 总结与后续学习方向看到这里你应该已经明白了完整的爬虫最小闭环用 requests 发请求用 BeautifulSoup 解析 HTML用 JSON、CSV 或 SQLite 保存数据。这三个环节可以拆开独立练习也能组合成一个完整脚本。从零基础角度说掌握这个闭环就已经超过了“只会复制代码”的阶段因为你已经能根据一个陌生页面独立写出针对性的采集代码。下一步的学习路径可以这样安排。先继续巩固静态网页解析把 BeautifulSoup 的 find、find_all、select 用熟。然后学习 XPath 和正则表达式它们在某些场景下比 BeautifulSoup 更灵活。再往后可以看看 Scrapy 框架你会更容易理解它的 Request、Response、Item 这些概念。如果页面是动态渲染的再学习接口抓包或浏览器自动化工具。最后给一个实用的建议维护一个自己的代码片段库。每次解决一个新的解析问题就把可复用的代码保存下来加上注释说明。爬虫没有什么“看一遍就会”的捷径但做得越多你对页面结构的敏感度会越高后面看什么网站都会很快找到切入点。按照本文的步骤先跑通最小闭环截图保存一份自己的输出结果你对爬虫的系统性认知就算真正打开了。建议收藏这篇文章动手实践时对照着看比单纯阅读有效得多。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门