ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Python爬虫入门实战:从requests请求到数据保存全流程

Python爬虫入门实战:从requests请求到数据保存全流程 很多刚开始接触 Python 的朋友一听到“爬虫”两个字总觉得是高阶玩法既要懂网络协议又要会写复杂的解析规则。其实爬虫最核心的套路就那么几步把网页拿下来从里面提取你要的数据再按需保存。只要顺着这条主线走哪怕没有任何编程基础也能在短时间内写出一个能真正跑起来的爬虫。本文会从 Python 环境安装开始一步一步带你完成 requests 请求、HTML 解析、数据保存、动态页面处理最后再用一个完整的实战案例把整条链路串起来。1. 爬虫到底是什么1.1 爬虫的本质爬虫本质上是“模拟浏览器访问网页并提取信息”的自动化程序。普通用户用浏览器打开一个页面看到的是排版好的图文内容爬虫程序做的事情是向目标网站发送 HTTP 请求拿到 HTML、JSON 或其它格式的响应再用代码从这些响应里解析出自己关心的数据。举个例子你想收集某个电商平台上的商品标题、价格和销量。手动复制粘贴几百条数据不现实但写一个 Python 脚本让它循环请求商品列表页再按标签或字段提取信息几分钟就能完成。这个自动化过程就是爬虫。1.2 爬虫的常见应用场景价格监控定时抓取商品价格降价时自动通知。数据采集收集新闻、招聘信息、房产信息用于分析。数据分析抓取公开数据集配合 pandas、matplotlib 做可视化。搜索引擎蜘蛛程序本质上也是爬虫。舆情监测采集评论、微博、贴吧内容做情感分析。需要注意的是爬虫技术本身是中性的但使用场景必须有边界。抓取公开数据时要尊重目标网站的 robots 协议控制请求频率避免对服务器造成压力更不能把抓取的数据用于商业侵权或泄露个人隐私。本文所有案例都只用于技术学习。1.3 初学者需要掌握的四个核心模块把爬虫拆开看其实只需要四个能力发起请求用 Python 模拟浏览器向服务器要数据。接收响应拿到服务器返回的 HTML 或 JSON。解析数据从响应中提取目标字段。保存数据把提取结果写入 CSV、Excel 或数据库。如果遇到需要点击、滚动才能加载的页面还需要“动态渲染页面处理”这个额外技能后面会专门讲。2. 环境准备与版本说明2.1 Python 安装绝大多数爬虫教程推荐 Python 3.8 以上版本。本文示例在 Python 3.10 环境下运行你本地装 3.9、3.11、3.12 均可语法和依赖库兼容性没有问题。Windows 用户去 Python 官网下载安装包时记得勾选“Add Python to PATH”否则后续在 cmd 里输入 python 会提示找不到命令。macOS 用户可以通过 Homebrew 安装brew install python3Linux 用户使用系统自带的包管理器即可。安装完成后在终端输入python --version如果输出了类似Python 3.10.12的版本号说明安装成功。2.2 虚拟环境爬虫会用到多个第三方库不同项目对库版本要求不同建议每个项目创建独立虚拟环境避免依赖冲突。mkdir python-spider-demo cd python-spider-demo python -m venv venvWindows 激活venv\Scripts\activatemacOS/Linux 激活source venv/bin/activate激活后终端前面会出现(venv)标记后面安装的依赖都只作用于当前项目。2.3 编辑器选择新手推荐 VS Code 或者 PyCharm。VS Code 需要安装 Python 扩展PyCharm 社区版开箱即用。两个编辑器都能直接运行.py文件也支持 Jupyter Notebook。如果只写脚本型爬虫用 VS Code 更轻量。2.4 核心依赖库本文实战会用到以下库在虚拟环境中统一安装pip install requests beautifulsoup4 lxml pandasrequests发送 HTTP 请求。beautifulsoup4解析 HTML 文档。lxml解析器解析速度比 Python 内置的 html.parser 更快。pandas数据清洗和保存 Excel/CSV。如果之后要抓取动态渲染页面还需要selenium和浏览器驱动在第五节单独讲。3. 第一个可运行的爬虫requests 请求与响应3.1 发送 GET 请求先用一个最简单的例子理解请求-响应过程。在项目目录下创建first_spider.pyimport requests url https://www.baidu.com response requests.get(url) print(状态码:, response.status_code) print(响应内容前500个字符:) print(response.text[:500])运行后你会看到状态码200以及百度首页的 HTML 源码。response.status_code表示服务器返回的 HTTP 状态码200 代表正常访问404 代表资源不存在403 代表禁止访问。response.text是服务器返回的文本内容通常就是 HTML 代码。3.2 处理响应编码很多网站的页面默认使用 UTF-8但部分网站可能是 GBK 或 GB2312 编码。如果不处理编码解析结果会出现乱码。建议先通过response.encoding查看实际编码再显式指定import requests url https://example.com response requests.get(url) print(原始编码:, response.encoding) # 手动指定编码 response.encoding utf-8 print(response.text)如果确定页面是 GBK比如一些老旧的政府网站或文学网站可以写成response.encoding gbk。3.3 设置请求头有些网站会拦截没有 User-Agent 的请求。服务器通过 User-Agent 判断发起请求的是不是真实浏览器。所以爬虫代码里最好设置请求头import requests 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 } url https://www.baidu.com response requests.get(url, headersheaders) print(response.status_code)这里的 User-Agent 是一个 Chrome 浏览器的标识。你可以打开自己浏览器的“开发者工具”在 Network 面板里查看任意请求的 User-Agent复制过来使用。3.4 处理超时与异常网络请求不稳定时程序会卡住甚至崩溃。给请求加上超时时间并用 try-except 捕获异常是爬虫的基本素养import requests 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 } url https://www.baidu.com try: response requests.get(url, headersheaders, timeout5) response.raise_for_status() print(请求成功:, response.status_code) except requests.RequestException as e: print(请求失败:, e)timeout5表示 5 秒内没有响应就抛出异常。raise_for_status()会在状态码不是 200 时主动抛错方便提前发现问题。4. 解析 HTMLBeautifulSoup 核心用法requests 拿到的是 HTML 字符串不能直接读取“标题”“价格”这样的字段需要用解析库把 HTML 转换成结构化对象。BeautifulSoup 是新手最友好的选择。4.1 从 HTML 字符串创建 BeautifulSoup 对象from bs4 import BeautifulSoup html html body h1 classtitlePython爬虫教程/h1 p iddesc这是一个示例页面/p ul lirequests/li liBeautifulSoup/li lipandas/li /ul /body /html soup BeautifulSoup(html, lxml) print(soup.title) print(soup.h1.text) print(soup.p.text)输出None Python爬虫教程 这是一个示例页面lxml作为解析器需要提前安装上一节已经装好。soup.h1匹配到第一个 h1 标签.text获取标签内的文本。4.2 查找单个元素findfind()返回第一个匹配的标签title_tag soup.find(h1) print(title_tag.text) # 按属性查找 desc_tag soup.find(p, iddesc) print(desc_tag.text)4.3 查找多个元素find_allfind_all()返回所有匹配标签的列表items soup.find_all(li) for item in items: print(item.text)输出requests BeautifulSoup pandas这是解析列表页最常用的方式先find_all拿到所有列表项再对每一项提取具体字段。4.4 CSS 选择器selectBeautifulSoup 的select()支持 CSS 选择器写起来更接近前端语法# 类选择器 title_tag soup.select(.title) print(title_tag[0].text) # id 选择器 desc_tag soup.select(#desc) print(desc_tag[0].text) # 标签选择器 li_tags soup.select(ul li) for li in li_tags: print(li.text)无论find还是select返回的都是 Tag 对象。要获取属性值比如链接地址使用中括号取值html a hrefhttps://example.com classlink点我/a soup BeautifulSoup(html, lxml) a_tag soup.find(a) print(a_tag[href])4.5 实战解析一个简单页面假设有一个本地 HTML 文件book_list.html!DOCTYPE html html head meta charsetutf-8 title图书列表/title /head body div classbook h2Python编程从入门到实践/h2 span classprice¥89.00/span a href/books/1详情/a /div div classbook h2流畅的Python/h2 span classprice¥128.00/span a href/books/2详情/a /div /body /html用代码提取所有书名和价格from bs4 import BeautifulSoup with open(book_list.html, r, encodingutf-8) as f: html f.read() soup BeautifulSoup(html, lxml) books soup.select(.book) for book in books: title book.find(h2).text price book.select_one(.price).text print(f书名: {title}, 价格: {price})输出书名: Python编程从入门到实践, 价格: ¥89.00 书名: 流畅的Python, 价格: ¥128.005. 动态页面解析Selenium 入门与常见方案5.1 什么是动态渲染页面有些网站的数据不是直接写在 HTML 源码里的而是通过 JavaScript 动态加载。用 requests 请求只能拿到一个空壳页面真正的数据要等浏览器执行完 JavaScript 后才出现。最常见的例子是电商页面下拉加载更多、数据大屏、登录后才显示的图表。简单判断方法用浏览器右键“查看网页源代码”如果目标数据不在源码中那么这个页面就是动态渲染的直接 requests 解析不到。5.2 方案一分析接口推荐动态页面背后往往有一个 ajax 接口返回 JSON 数据。打开浏览器开发者工具 - Network - XHR刷新页面找到返回数据的请求直接用 requests 请求该接口解析 JSON 即可。这样效率最高也不依赖浏览器。以常见的数据接口为例import requests import json headers { User-Agent: Mozilla/5.0 ..., Referer: https://example.com/data.html } url https://example.com/api/data params { page: 1, pageSize: 10 } response requests.get(url, headersheaders, paramsparams, timeout5) data response.json() print(json.dumps(data, ensure_asciiFalse, indent2))注意编码参数ensure_asciiFalse否则中文会变成\u开头的一串字符。5.3 方案二Selenium 模拟浏览器当接口难以分析或者页面交互复杂时用 Selenium 模拟真实浏览器是最稳妥的方案。Selenium 需要安装第三方库和浏览器驱动本文以 Chrome 为例。安装 seleniumpip install selenium还需要安装与本地 Chrome 版本匹配的 ChromeDriver。你可以打开 Chrome在地址栏输入chrome://version查看版本号然后去 ChromeDriver 官网下载对应版本并把驱动所在目录加入 PATH或者直接把驱动放到项目目录下。简单示例from selenium import webdriver from selenium.webdriver.common.by import By import time # 创建浏览器对象 driver webdriver.Chrome() # 打开页面 driver.get(https://example.com) # 等待页面加载 time.sleep(3) # 获取页面文本 page_text driver.find_element(By.TAG_NAME, body).text print(page_text) # 关闭浏览器 driver.quit()Selenium 最关键的是等待元素出现。用time.sleep虽简单但不稳定更推荐显式等待from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver webdriver.Chrome() driver.get(https://example.com) try: element WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CLASS_NAME, book-title)) ) print(element.text) finally: driver.quit()WebDriverWait会每隔一段时间检查一次元素是否出现10 秒超时后抛出异常。这种写法比固定 sleep 更可靠。5.4 方案三存储与复用页面数据动态页面的爬虫运行较慢如果数据量不大可以先把页面源码保存到本地再离线解析减少重复请求。from selenium import webdriver import time driver webdriver.Chrome() driver.get(https://example.com) time.sleep(3) html driver.page_source with open(page.html, w, encodingutf-8) as f: f.write(html) driver.quit()之后使用 BeautifulSoup 读取本地文件解析即可。6. 数据保存CSV、Excel 的简洁写法爬虫抓到的数据如果不保存程序一结束就没了。最常见的保存格式是 CSV 和 Excel。CSV 是纯文本表格通用性最强Excel 适合后续可视化或交给非技术同事查看。6.1 保存为 CSV使用 Python 内置的 csv 模块不需要额外安装import csv data [ {书名: Python编程从入门到实践, 价格: 89.00}, {书名: 流畅的Python, 价格: 128.00}, ] with open(books.csv, w, encodingutf-8-sig, newline) as f: writer csv.DictWriter(f, fieldnames[书名, 价格]) writer.writeheader() writer.writerows(data)注意编码要写成utf-8-sig否则用 Excel 打开 CSV 时中文可能乱码。newline是为了避免 Windows 下出现多余空行。6.2 保存为 Excel使用 pandas一行代码即可写出 Excel 文件。需要先安装openpyxlpip install openpyxl代码import pandas as pd df pd.DataFrame(data) df.to_excel(books.xlsx, indexFalse)这也是爬虫与数据分析结合的关键一步爬下来的数据交给 pandas可以直接做清洗、筛选和汇总。6.3 追加写入模式如果爬虫是多轮运行需要把新数据追加到已有文件而不是覆盖可以改成import csv def save_to_csv(file_name, data): with open(file_name, a, encodingutf-8-sig, newline) as f: writer csv.DictWriter(f, fieldnames[书名, 价格]) writer.writerows(data)如果文件是首次创建需要先写表头这里需要结合文件是否存在做判断更完善的写法建议使用 pandas 读取已有文件后合并再写回既避免重复表头也能做去重。7. 完整实战抓取一个静态新闻列表前面所有知识点都很零散现在用一个完整案例把“请求 - 解析 - 保存”串起来。我们以“某公开的测试新闻网站”为例演示如何抓取文章标题、链接和发布时间。请确保你使用的是可公开访问、允许爬虫测试的站点这里只演示技术逻辑。7.1 需求分析目标抓取首页新闻列表的前 20 条记录字段包括文章标题、文章链接、发布时间。页面结构假设如下div classnews-list div classnews-item a href/news/1标题1/a span classdate2025-01-01 10:00:00/span /div div classnews-item a href/news/2标题2/a span classdate2025-01-02 11:00:00/span /div /div7.2 创建项目文件项目结构python-spider-demo/ ├── venv/ ├── news_spider.py └── news.csv7.3 编写爬虫代码import csv import requests from bs4 import BeautifulSoup BASE_URL https://example.com/news 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 } def fetch_page(url): try: response requests.get(url, headersheaders, timeout5) response.raise_for_status() response.encoding utf-8 return response.text except requests.RequestException as e: print(f请求失败: {e}) return None def parse_news(html): soup BeautifulSoup(html, lxml) news_items soup.select(.news-item) result [] for item in news_items: title_tag item.find(a) if title_tag is None: continue title title_tag.text.strip() link title_tag[href] date_tag item.find(span, class_date) date date_tag.text.strip() if date_tag else result.append({ 标题: title, 链接: link, 发布时间: date }) return result def save_to_csv(data, filenamenews.csv): with open(filename, w, encodingutf-8-sig, newline) as f: writer csv.DictWriter(f, fieldnames[标题, 链接, 发布时间]) writer.writeheader() writer.writerows(data) if __name__ __main__: html fetch_page(BASE_URL) if html: news_data parse_news(html) save_to_csv(news_data) print(f成功保存 {len(news_data)} 条新闻到 news.csv) else: print(页面抓取失败)7.4 运行与验证在终端运行python news_spider.py如果成功会输出成功保存 20 条新闻到 news.csv打开news.csv可以看到整齐的表格数据。这里的parse_news是核心函数它先用select(.news-item)定位所有新闻块再在每一块中提取标题、链接和日期。strip()用于去掉首尾空白字符。7.5 扩展翻页抓取如果新闻列表有多页通常 URL 规律是https://example.com/news?page2。可以写一个循环for page in range(1, 6): url fhttps://example.com/news?page{page} html fetch_page(url) if html: data parse_news(html) all_data.extend(data) save_to_csv(all_data)注意请求间隔不要连续快速请求。可以在循环中加入time.sleep(1)避免对服务器造成压力。8. 常见问题与排查思路爬虫开发中遇到的报错80% 都是下面这几类问题。遇到报错不要慌按表格中的思路逐个排查。问题现象常见原因解决思路请求返回 403服务器拒绝了请求缺少 User-Agent 或被识别为爬虫添加浏览器 UA必要时增加 Referer、Cookie返回 404请求的 URL 不存在或拼接参数错误检查 URL 拼接方式先用浏览器访问确认返回 200 但解析不出数据页面内容由 JavaScript 动态渲染改用 Selenium或直接分析 XHR 接口结果出现乱码页面编码与 response.encoding 不一致手动设置编码如 gbk、utf-8中文写入 CSV 后乱码编码用了 utf-8Excel 默认不识别写入时使用encodingutf-8-sigSelenium 找不到元素元素未加载完成或选择器错误使用显式等待先在浏览器 F12 里验证选择器请求超时目标网站响应慢或本地网络问题增大 timeout添加重试机制8.1 请求头需要带哪些内容最少要有User-Agent。部分网站会校验Referer表示请求是从哪个页面跳转过来的。遇到登录后才能查看的数据还需要在请求头中携带 Cookie。Cookie 可以从浏览器的开发者工具里复制但要注意 Cookie 有过期时间长期运行的爬虫需要维护登录态。8.2 如何提高数据解析的准确率解析前先用浏览器 F12 查看目标元素最外层容器的 class 或 id选择稳定的容器节点再逐层提取。不要直接拿整段文本做字符串截取那样遇到页面调整就会失效。BeautifulSoup 的select加上完整的父子层级是通用性较强的写法。8.3 反爬策略有哪些常见反爬手段包括User-Agent 检测、请求频率检测、IP 访问次数限制、验证码、登录限制、动态加密参数。作为初学者先从最基础的请求头伪装和访问频率控制做起。验证码和加密参数属于进阶内容不建议刚入门就死磕。9. 最佳实践与工程建议9.1 网络请求质量设置超时时间防止线程卡死。对失败的请求做重试建议最多 2-3 次间隔至少 1 秒。控制请求频率平均每次请求间隔 1-3 秒并发场景下也要设置限速。尽量避开目标网站的高峰访问时段比如大型电商大促期间。9.2 数据存储设计小数据量用 CSV便于查看和分享。结构复杂、需要频繁查询的数据存 SQLite 或 MySQL。每一条数据最好保留抓取时间和来源 URL方便溯源。做增量爬虫时用主键或标题去重避免重复入库。9.3 代码可维护性把请求、解析、保存拆成独立函数不要全部塞在 main 里。URL 和请求头等常量统一放在文件顶部。解析逻辑与页面结构强相关建议在注释里写明页面示例片段。多页面爬虫用配置文件管理 URL 规则和字段映射。9.4 安全与合规边界强烈建议遵守以下原则只抓取明确允许公开访问的数据。检查目标网站的 robots.txt了解哪些路径不允许抓取。不抓取包含个人身份信息、账号密码、非公开交易数据的内容。抓取频率不要影响目标网站正常服务。爬取的数据仅用于个人学习和研究不用于非法用途或商业牟利。涉及用户数据的项目先咨询法务或相关合规人员。10. 进一步学习路线从零基础到能独立写爬虫可以按下面顺序推进熟练掌握 requests 请求头和响应处理。熟练使用 BeautifulSoup 的 find、find_all、select。学习 XHR 接口分析用 requests 抓 JSON 数据。学习 Selenium 处理动态页面。学习 scrapy 框架实现分布式爬虫和更稳定的调度。配合正则表达式处理复杂文本。掌握数据清洗与可视化把爬虫结果真正用起来。如果你能完整跑完本文的案例说明你已经具备了爬虫的基础链路能力。可以再找一个公开的静态列表网站自己动手改代码把标题解析改成图片地址解析把 CSV 输出改成 Excel 输出多练几个不同结构的页面比继续看教程更有效。技术就是这样看十遍不如自己写一遍。希望这篇 Python 爬虫入门教程能帮你迈出第一步。
返回列表