ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python爬虫入门教程:从零基础到豆瓣Top250实战全解析

Python爬虫入门教程:从零基础到豆瓣Top250实战全解析 很多初学者在接触 Python 时最想做的第一个实战项目就是网络爬虫。一方面是因为爬虫能快速看到“程序自动拿到网页数据”的效果成就感很强另一方面爬虫涉及的知识点非常综合能把 Python 基础语法、网络请求、数据解析、文件保存等内容串在一起。本文就来整理一套适合零基础入门的 Python 爬虫教程从环境安装开始到写一个能跑通的完整案例再到常见报错与排查思路全程用最简单的语言和可复制的代码带你走一遍。如果你完全没有任何编程基础也能跟着本文的操作步骤一步步做。文章里不会一次性塞太多高深概念而是先把最核心的知识讲清楚再通过一个真实案例把代码跑起来。如果你已经有了一点 Python 基础也可以用这篇教程来补齐 requests、BeautifulSoup、数据清洗这些爬虫常用技术。1. Python爬虫到底是什么先建立整体认知1.1 爬虫的作用与运行过程网络爬虫Web Crawler可以理解为一个自动浏览网页的程序。正常人类浏览网页时是在浏览器里输入网址、点击链接、查看内容而爬虫则是用代码模拟这个过程自动向服务器发送请求、接收网页源码、提取自己需要的信息。它解决的问题是“重复性的数据收集工作”比如每天查看某几个商品的价格、采集新闻标题、统计招聘网站的岗位需求等。爬虫的实际应用场景非常广泛。搜索引擎需要爬虫去全网抓取页面并建立索引数据分析师需要用爬虫采集公开数据来做统计和可视化运营人员可以用爬虫监控竞品信息大学生也可以用它做课程设计、毕业设计的数据采集。可以说只要是想从网页上批量获取公开数据爬虫都是最直接的工具。从技术角度来说一个最简爬虫的完整运行过程包含四步构造请求确定目标网址准备好请求头、参数等信息。发送请求用 requests 等库把请求发出去拿到服务器返回的 HTML 源码。解析内容在 HTML 中找到需要的数据通常是标题、链接、价格、正文等字段。保存数据把提取出的结构化数据写入 CSV、Excel、数据库或 JSON 文件。下面这张简图可以帮助你理解整个过程浏览器地址输入网址 ↓ 程序构造请求URL 请求头 ↓ 服务器返回 HTML 源码 ↓ 解析页面定位标题/链接/正文 ↓ 保存数据CSV/Excel/数据库1.2 爬虫技术栈总览与学习路径Python 爬虫相关的库非常多但新手并不需要一开始就全部掌握。最常用的核心组合有三部分requests负责发送 HTTP 请求拿到网页源码。BeautifulSoup4负责解析 HTML 源码定位和提取需要的标签内容。lxmlBeautifulSoup 的解析器解析速度比 Python 自带解析器更快。这三个库就足够完成绝大多数入门爬虫任务。等你熟悉了这套流程再考虑学习 Scrapy 框架、Ajax 数据接口爬取、Selenium 模拟浏览器、分布式爬虫等进阶内容。第一周requests BeautifulSoup → 能爬静态网页 第二周JSON接口 数据清洗 → 能爬动态网页的数据接口 第三周Scrapy 框架 → 工程化爬虫 第四周反爬应对 分布式 → 进阶提升对于零基础的朋友我建议先把“能爬静态页面”这个目标定下来不用急着学框架。静态页面已经能覆盖很多信息采集需求而且能帮助你建立完整的爬虫思维。1.3 法律与道德边界这部分非常重要必须放在学习的最前面说清楚。Python 爬虫本身是一门中性技术但使用不当可能会带来法律风险。入门阶段要记住几个原则只抓取公开数据不抓取需要登录才能访问的隐私数据。遵守目标网站的 robots.txt 协议它明确说明了网站允许和禁止抓取的路径。控制请求频率不要对服务器发起高并发请求。不要用爬虫做恶意攻击、刷票、薅羊毛、绕过付费等行为。抓取到的数据不要用于商业牟利尤其涉及个人隐私、版权内容时要格外谨慎。一句话总结爬虫技术本身没有错但使用边界必须清楚。本文所有案例都选择公开网站、公开数据并且控制抓取频率希望大家在练习时也保持同样的习惯。2. 环境准备从零搭建Python开发环境2.1 Python 安装与环境变量配置如果你还没有安装 Python需要先到 Python 官网下载安装包。不同操作系统略有差异这里给出最关键的注意事项。Windows 用户在安装 Python 时一定要勾选底部的 “Add Python to PATH” 选项。这个选项会自动把 Python 加入环境变量否则后面在命令行输入python时会出现“不是内部或外部命令”的提示。安装完成后打开命令行Windows 按Win R输入cmd回车执行以下命令验证安装结果python --version如果输出类似Python 3.11.5这样的版本号说明安装成功。Python 3 的语法和生态在目前最常用本文的代码也基于 Python 3。macOS 和 Linux 大多数情况自带 Python 3但版本可能较旧。如果执行python3 --version能输出版本号也可以直接使用。如果系统版本太旧建议安装最新的稳定版 Python。2.2 IDE 选择与项目目录规划Python 开发常用的编辑器有 VS Code、PyCharm、Sublime Text 等。初学者可以从 VS Code 开始它免费、轻量、安装扩展方便。VS Code 装好后建议安装以下扩展Python微软官方扩展提供语法高亮、智能提示、运行调试功能。Pylance配合 Python 扩展使用提供更智能的代码补全。安装 VS Code 后新建一个专门用于爬虫学习的目录例如python-crawler-demo。这个目录下再创建一个.py文件用于写代码。项目目录结构建议如下python-crawler-demo/ ├── 01_requests_demo.py # requests 基础请求 ├── 02_bs4_demo.py # BeautifulSoup 解析练习 └── 03_douban_top250.py # 完整爬虫案例把不同阶段的练习拆成多个文件比全部堆在一个文件里更容易排查问题。2.3 安装第三方库爬虫需要用到的 requests、beautifulsoup4、lxml 都不是 Python 自带库需要手动安装。打开命令行或 VS Code 的终端执行以下命令pip install requests beautifulsoup4 lxml如果你电脑里同时有 Python 2 和 Python 3可能需要用 pip3 指定安装pip3 install requests beautifulsoup4 lxml安装完成后可以先用一个简单的测试验证库是否可用。新建test_env.py写入以下内容import requests from bs4 import BeautifulSoup print(requests 版本:, requests.__version__) print(BeautifulSoup 版本:, BeautifulSoup.__version__) print(环境准备成功)运行这个文件如果程序能正常运行并输出版本号说明环境已经准备好了。后面所有的代码都可以在这个环境里运行。3. 爬虫核心知识拆解3.1 理解HTTP请求与响应爬虫的第一步是向服务器发送请求而互联网上网页传输使用的协议是 HTTPHyperText Transfer Protocol超文本传输协议。当一个请求发出后服务器会返回一个响应其中最重要的部分是状态码告诉程序请求是否成功。200 表示成功404 表示页面不存在403 表示禁止访问500 表示服务器内部错误。响应头包含服务器类型、内容类型、Set-Cookie 等信息。响应体网页的 HTML 源码也就是爬虫需要解析的内容。请求本身也有多种类型最常用的是 GET 和 POST。GET 通常用于获取数据参数直接拼接在 URL 后面POST 通常用于提交表单或发送数据参数放在请求体中。# 简单请求 url https://www.example.com response requests.get(url) print(response.status_code) # 查看状态码 print(response.text) # 查看页面源码3.2 requests 库基础用法requests 是 Python 中最常用的 HTTP 请求库它的设计让发送请求变得非常简单。下面从几个关键场景来掌握它。发送 GET 请求并设置请求头很多网站会检查请求头里的User-Agent用于识别客户端的类型。默认情况下requests 的 User-Agent 是python-requests/x.x.x这种标识很容易被服务器拒绝。我们可以通过修改请求头来模拟浏览器访问。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.example.com response requests.get(url, headersheaders, timeout10) print(response.status_code) print(response.text)timeout10表示 10 秒内没有响应就放弃请求避免程序卡死。发送带参数的请求很多动态网站的列表页是通过 URL 参数控制分页的比如https://example.com/list?page1。参数可以用字典传入import requests params { page: 1, keyword: python } url https://www.example.com/search response requests.get(url, paramsparams, timeout10) print(response.url) # 打印最终请求的完整URL print(response.text)使用 Session 保持会话如果需要在多个请求之间保持登录状态、Cookie 等信息推荐使用 Session。Session 对象会保持会话信息适用于需要登录后才能访问的页面。import requests session requests.Session() session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 }) response session.get(https://www.example.com, timeout10)常用响应对象属性属性/方法作用response.status_code获取 HTTP 状态码response.text获取响应文本内容HTML 源码response.url获取最终请求的 URLresponse.encoding获取响应编码response.json()如果接口返回 JSON可直接解析为字典response.content获取响应内容的二进制形式适合下载图片3.3 使用 BeautifulSoup 解析HTML获取到 HTML 源码后还不能直接使用因为 HTML 是标签嵌套的文档我们需要从标签中精确提取目标数据。BeautifulSoup 就是做这件事的。BeautifulSoup 的使用主要有两步第一步把 HTML 字符串转换成 BeautifulSoup 对象第二步调用 find、find_all 等方法定位标签。基本解析示例from bs4 import BeautifulSoup html html head titlePython爬虫教程/title /head body div classcontent h1爬虫基础学习/h1 a hrefhttps://example.com/a classlink链接A/a a hrefhttps://example.com/b classlink链接B/a /div /body /html soup BeautifulSoup(html, lxml) # 获取标题 title soup.title print(title.text) # 输出Python爬虫教程 # 获取第一个 a 标签 first_a soup.find(a) print(first_a.text) # 链接A print(first_a.get(href)) # https://example.com/a # 获取所有 a 标签 all_a soup.find_all(a) for a in all_a: print(a.text, a.get(href))按照 class 属性定位真实网页中标签非常多只按标签名无法精确找到目标。此时可以配合 class 属性定位# 找 classlink 的 a 标签 result soup.find_all(a, class_link) # 找 idcontent 的 div 标签 div_content soup.find(div, idcontent)使用 CSS 选择器BeautifulSoup 还支持类似 CSS 的 select 方法这种写法在某些场景更简洁# 选择 classcontent 下的所有 a 标签 links soup.select(.content a) # 选择 idheader 的元素 header soup.select(#header)常用属性和方法速查操作代码获取标签文本tag.text 或 tag.get_text()获取标签属性tag.get(href) 或 tag[href]获取第一个匹配标签soup.find(a)获取所有匹配标签soup.find_all(a)按 class 查找soup.find_all(div, class_title)CSS 选择器soup.select(.title a)需要特别提醒的是class是 Python 的关键字所以 BeautifulSoup 中必须写成class_后面带一个下划线。这是一个十分常见的书写错误。3.4 翻页爬取与数据清洗在实际项目中我们经常需要爬取整个列表的多页数据。翻页的本质是找到 URL 的变化规律然后循环请求不同的页码。例如某网站列表页的 URL 格式是https://example.com/list?page1 https://example.com/list?page2 https://example.com/list?page3这时可以用循环生成多个请求import requests headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } base_url https://example.com/list for page in range(1, 6): params {page: page} response requests.get(base_url, headersheaders, paramsparams, timeout10) print(f第{page}页状态码:, response.status_code)当获取到数据后还需要考虑清洗。网页源码中经常包含空格、换行、HTML 实体等脏数据可以用 strip()、replace() 等方法处理text Python爬虫教程 \n clean_text text.strip() print(clean_text) # 输出Python爬虫教程4. 完整实战抓取豆瓣电影Top250理论讲再多不如实战跑一遍。这一节我们用一个大家熟知的案例——豆瓣电影 Top250完成一个真正可运行的爬虫程序。4.1 需求分析与爬取流程豆瓣电影 Top250 的地址是https://movie.douban.com/top250。这个页面展示了 250 部高分电影每页展示 25 部共 10 页。我们的目标是抓取每一页的电影数据包括电影排名电影名称导演和主演信息上映年份评分评语摘要爬取流程如下分析 Top250 页面的 URL 分页规律。发送带浏览器 User-Agent 的请求。使用 BeautifulSoup 解析页面中的电影信息。循环爬取 10 页把所有数据保存到 CSV 文件。4.2 分析网页结构打开豆瓣电影 Top250 页面按 F12 打开开发者工具点击左上角的箭头图标再点击页面上的电影标题可以看到对应的 HTML 结构。Top250 中每一部电影都放在li标签内关键结构如下li div classitem div classpic em class1/em a hrefhttps://movie.douban.com/subject/1292052/ img src... class / /a /div div classinfo div classhd a href... span classtitle肖申克的救赎/span span classtitlenbsp;/nbsp;The Shawshank Redemption/span /a /div div classbd p class 导演: 弗兰克·德拉邦特 ... 主演: 蒂姆·罗宾斯 ... br/ 1994nbsp;/nbsp;美国nbsp;/nbsp;犯罪 剧情 /p div classstar span classrating5-t/span span classrating_num9.7/span span propertyv:best content10.0/span span约...人评价/span /div p classquote span classinq希望让人自由。/span /p /div /div /div /li分析出的关键选择器如下电影排名em标签的文本电影名称span.title的文本导演和主演信息p标签的文本评分span.rating_num的文本评语摘要span.inq的文本链接的 URL 规律是https://movie.douban.com/top250?start25每页间隔 25第二页是start25第三页是start50依次类推。4.3 编写爬虫代码在项目目录下新建douban_top250.py写入完整代码。这个版本先用最简单的方式实现便于理解整体流程。# 文件路径python-crawler-demo/douban_top250.py import time import csv import requests from bs4 import BeautifulSoup 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(start): 请求豆瓣Top250单页数据返回HTML文本 url fhttps://movie.douban.com/top250?start{start} response requests.get(url, headersheaders, timeout10) response.encoding utf-8 if response.status_code 200: return response.text else: print(f请求失败状态码: {response.status_code}) return None def parse_page(html): 解析HTML提取电影信息返回列表 soup BeautifulSoup(html, lxml) movies [] # 每一部电影都在 li 标签内 items soup.select(.grid_view .item) for item in items: rank item.select_one(em).text title item.select_one(.title).text rating item.select_one(.rating_num).text # 导演、主演、年份信息在 bd 区域的 p 标签中 info_p item.select_one(.bd p).text.strip() # 这里只简单取出年份示例数据格式为 1994 / 美国 / 犯罪 剧情 year info_p.split(/)[0].strip() quote_span item.select_one(.inq) quote quote_span.text if quote_span else movies.append({ ranking: rank, title: title, rating: rating, year: year, quote: quote }) return movies def save_to_csv(movies): 将电影数据保存到CSV文件 with open(douban_top250.csv, a, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[ranking, title, rating, year, quote]) # 如果是第一次写入先写入表头 if f.tell() 0: writer.writeheader() writer.writerows(movies) if __name__ __main__: for page in range(10): start page * 25 print(f正在爬取第 {page 1} 页start{start} ...) html fetch_page(start) if html: movie_list parse_page(html) save_to_csv(movie_list) print(f第 {page 1} 页抓取到 {len(movie_list)} 条数据) # 控制请求速度避免给服务器造成压力 time.sleep(2) print(全部页面爬取完成数据已保存到 douban_top250.csv)这段代码一共拆成了四个函数每个函数都有明确职责fetch_page负责请求网页。parse_page负责解析网页并提取字段。save_to_csv负责数据保存。主流程负责翻页并控制请求间隔。4.4 运行与验证在项目目录下执行python douban_top250.py运行过程中会输出如下类似信息正在爬取第 1 页start0 ... 第 1 页抓取到 25 条数据 正在爬取第 2 页start25 ... 第 2 页抓取到 25 条数据 ... 全部页面爬取完成数据已保存到 douban_top250.csv打开生成的douban_top250.csv文件内容示例rankingtitleratingyearquote1肖申克的救赎9.71994希望让人自由。2霸王别姬9.61993风华绝代。3阿甘正传9.51994一部美国近现代史。4.5 代码优化与扩展思路上面的代码已经能完成基本需求但实际项目中我们还需要考虑几个优化点。加入异常重试机制网络请求可能因为超时、临时封禁等原因失败可以加入重试逻辑import time import requests from requests.adapters import HTTPAdapter session requests.Session() session.mount(https://, HTTPAdapter(max_retries3))加入请求头中的 Referer部分网站会校验请求来源可以在 headers 中加入 Referer 字段模拟从网站内部跳转headers { User-Agent: Mozilla/5.0 ..., Referer: https://movie.douban.com/top250 }使用 csv 模块还是 pandas对于初学者直接使用 csv 模块不引入额外依赖是更稳妥的选择。如果之后需要做数据分析或可视化可以改用 pandas 保存import pandas as pd df pd.DataFrame(movie_list) df.to_excel(douban_top250.xlsx, indexFalse)不过注意导出 Excel 需要安装 openpyxlpip install openpyxl批量型、增量型与垂直型爬虫的概念入门之后你会接触更多爬虫分类。批量型爬虫一次性抓取大量历史数据增量型爬虫只抓取更新过的内容适合做持续监控垂直型爬虫针对特定行业或站点做深度抓取。本文的豆瓣案例属于最典型的批量型爬虫学习完这个例子你可以再尝试把它改造成增量型爬虫例如每天只抓取评分变化的数据。5. 常见报错与排查思路初学者写爬虫时最容易被各种报错卡住。下面整理几类最常见的问题并给出排查方向和解决方案。5.1 报错速查表问题现象常见原因解决思路requests.exceptions.ConnectionError无法连接到目标服务器检查网络连接、URL 是否正确requests.exceptions.ConnectTimeout连接超时增加 timeout 参数检查目标站是否可访问requests.exceptions.ReadTimeout响应内容读取超时增大 timeout或使用 Session 并设置重试HTTP 403 Forbidden服务器拒绝访问添加 User-Agent、Referer 等请求头HTTP 418 或 429触发反爬或访问频率过高降低请求频率增加延时不要高并发UnicodeDecodeError编码格式不匹配设置 response.encoding utf-8AttributeError: NoneType object has no attribute text未找到目标标签打印 HTML 并检查选择器是否正确EncodingWarning 或乱码页面编码识别错误使用 response.apparent_encoding 自动检测ModuleNotFoundError: No module named requests第三方库未安装执行 pip install requests5.2 请求阶段错误这一类错误发生在发送请求时最常见的是连接错误和超时。import requests from requests.exceptions import RequestException url https://movie.douban.com/top250 try: response requests.get(url, timeout10) response.raise_for_status() # 状态码不是200时会抛出异常 print(response.text) except RequestException as e: print(请求出错:, e)raise_for_status()会在状态码为 4xx、5xx 时主动抛错这样就不用每次手动判断状态码。如果遇到 403、418 一类的反爬拦截最直接的解决办法是先检查请求头确认 User-Agent 是浏览器标识。有些站点还会校验 Cookie、Referer可以通过抓包工具获取完整的请求头信息复制到代码中。5.3 解析阶段错误解析阶段最常见的错误是find返回None然后对None调用.text导致报错。quote_span soup.select_one(.inq) # 如果页面里没有这个标签quote_span 会是 None quote quote_span.text if quote_span else 这种写法能有效避免空值问题。如果网页结构发生变化比如 class 名称改了也会导致解析不到数据。此时不要盲目猜测选择器应该先打印一段 HTML 源码用开发者工具重新定位标签。5.4 数据保存乱码问题在 Windows 系统下用 Excel 打开 CSV 文件时经常出现中文乱码。解决方法是写入时指定utf-8-sig编码因为它会在文件开头加入 BOM 头Excel 才能正确识别with open(output.csv, w, newline, encodingutf-8-sig) as f: writer csv.writer(f) writer.writerow([标题, 评分])如果出现数据格式问题比如年份里混入空格、评分是字符串类型可以在保存前用 strip() 和类型转换处理。6. 工程化建议与进阶方向6.1 重视异常处理与日志记录入门阶段很多人写完爬虫就直接运行但真实项目中网络环境并不稳定。建议在关键位置添加异常捕获并输出有意义的日志而不是让程序静默失败或直接崩溃。import logging logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s ) logging.info(开始爬取第 1 页) logging.warning(请求失败准备重试) logging.error(重试超过最大次数跳过该页)日志的作用是让程序的可维护性更高。爬虫跑到第 8 页时如果突然报错没有日志的话很难定位问题出在哪一步。6.2 请求频率控制与重试策略抓取频率过高是爬虫被封禁的最主要原因。入门阶段一个非常实用的做法是每请求一页至少睡眠 1 到 3 秒。import time import random # 每两次请求之间随机等待 1~3 秒降低访问特征 time.sleep(random.uniform(1, 3))随机延时比固定延时的效果更好因为固定间隔的请求特征过于明显。如果要抓取的页面很少也可以不延时但如果要抓取大量页面延时是必备保护措施。6.3 明确保存数据后还要做什么爬虫爬下来的数据往往还要经过清洗、去重、分析才能产生价值。这里给出一条完整的数据链路爬虫采集 → 数据清洗 → 数据存储 → 数据分析 → 数据可视化你可以用 pandas 对爬取结果做分组统计用 matplotlib 或 pyecharts 做可视化图表这部分正好是 Python 数据处理最擅长的领域。6.4 常见的爬虫增强方向学完本文的内容后你可以从以下几个方向继续深入Scrapy 框架把爬虫工程化支持并发请求、中间件、管道处理适合大规模爬虫项目。Ajax 动态接口很多网站的页面内容是 JavaScript 动态渲染的直接请求 HTML 拿不到数据。这时候可以用开发者工具分析 XHR 请求直接请求 JSON 数据接口。自动化浏览器对于需要模拟用户点击、滚动、登录的复杂页面可以使用 Selenium 或 Playwright。分布式爬虫当单机爬虫效率不够时可以通过消息队列、任务调度等方式把任务分发到多台机器。学习这些方向时始终要记得控制请求频率、遵守 robots 协议、只抓公开数据。7. 写在最后的总结本文从零开始讲解了 Python 爬虫的核心原理和完整实现过程。我们从网络请求和 HTML 解析这两个最基本的概念入手掌握了 requests 和 BeautifulSoup 的使用方法然后通过豆瓣电影 Top250 这个真实案例完整跑通了一个翻页爬虫并把结果保存到了 CSV 文件。学完这篇文章你应该已经具备以下能力安装 Python 环境、使用 requests 获取网页源码、使用 BeautifulSoup 提取标签数据、处理翻页逻辑、把数据保存为 CSV、排查常见的请求和解析问题。这些是一条爬虫最基本的完整链路也是后续学习 Scrapy 等高阶框架的基础。下一步我推荐你动手做两个小练习来巩固知识第一个把豆瓣案例改成采集某一类图书的豆瓣 Top100第二个找一个静态新闻网站爬取首页的文章标题和链接用 pandas 统计一下不同关键词的出现频率。练完这两个项目你对爬虫的掌握会明显不一样。爬虫是一门实践的学问看再多的文章都不如自己跑通一遍。建议你打开编辑器照着本文的代码亲手敲一遍遇到报错也别怕根据上面的排查表格逐项检查很快就能解决。如果这篇文章对你有帮助可以收藏备用也欢迎在评论区交流你运行代码时遇到的问题一起进步。
返回列表