ARTICLE DETAIL

资讯详情

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

Python网络爬虫零基础入门:从环境搭建到Scrapy实战

Python网络爬虫零基础入门:从环境搭建到Scrapy实战 很多零基础读者刚开始学 Python 网络爬虫时最容易卡在三个环节一是环境配置折腾半天看着报错不知道从哪下手二是搞不明白网页结构和请求原理代码照着抄却什么都抓不到三是好不容易抓到数据又不知道怎么清洗和保存。网上相关的资料虽然多但要么只讲 requests 基础用法要么直接丢出一个 Scrapy 框架让新手一脸懵。这篇文章打算围绕零基础入门的视角把 Python 网络爬虫从环境搭建、基础语法、数据解析到工程化实战的完整路径整理出来。无论你是正在学 Python 的学生还是工作后需要快速采集公开数据的开发者都可以按这篇文章的顺序一步步操作。文章中涉及的每个代码示例都可以直接复制运行遇到报错也能在后面的常见问题部分找到对应的排查思路。1. 网络爬虫是什么能做什么1.1 爬虫的通俗理解网络爬虫简单来说就是一段自动化获取网页数据的程序。平时我们在浏览器里打开一个网页看到的是图片、文字和排版这些内容本质上都是 HTML 代码。爬虫做的事情就是模拟浏览器向服务器发送请求、接收响应然后从返回的 HTML 或其他格式数据中提取出我们关心的内容。举个例子你在电商网站上看到某件商品的价格是 399 元如果每天手动刷新页面去记录价格变化效率太低。写成爬虫程序后可以让它定时自动访问商品页面把价格、库存、评价数量提取出来存进表格。这就是爬虫最典型的应用场景。专业一点的定义是网络爬虫是一种按照一定规则自动请求网络资源并提取所需数据的程序或脚本。它通常包含三个核心步骤请求、解析、存储。1.2 常见应用场景爬虫的应用范围非常广泛至少要了解以下几种典型场景场景说明数据采集与分析采集公开的新闻、论文、商品信息用于数据分析或市场调研价格监控定时抓取电商平台的价格发现降价后自动提醒搜索引擎搜索引擎的爬虫会遍历互联网页面建立索引供用户检索舆情监测采集社交平台、新闻评论中的公开内容分析舆论方向学术研究获取开源的科研数据、论文元数据等公开信息需要注意的是爬虫本身是中性技术但使用边界非常关键。抓取公开的、允许访问的数据用于个人学习和研究是常见做法但如果抓取需要登录才能访问的私有数据、个人隐私信息或者高频请求对目标服务器造成压力就可能涉及法律和合规问题。这篇文章中涉及的示例都会选用公开的测试网站生产环境使用爬虫前请务必确认 robots.txt 和网站的访问条款。1.3 学习爬虫需要的前置知识不少新手会问我 Python 基础还不牢固能学爬虫吗答案是可以但有最低门槛。你需要掌握以下 Python 基础内容变量、列表、字典、元组等基本数据类型for 循环、while 循环和条件判断函数的定义和调用文件读写的基本操作异常处理的基本语法此外还需要对 HTML 有最基础的认识。不需要你会写出漂亮的页面只需要能看懂div、a、span、class、id这些常见的标签和属性含义。这部分内容在后面的解析章节中会边用边讲不需要预先系统学习。2. 环境准备与 Python 安装2.1 安装 Python 解释器爬虫程序最常用的语言是 Python所以第一步是安装 Python。访问 Python 官网下载页选择适配自己操作系统的安装包。注意以下几点不要安装太老的版本也不要盲目追求最新版本建议选择当前官方稳定版本如果使用的是 3.8 以上版本下面的爬虫相关代码都能正常运行在 Windows 上安装时务必勾选“Add Python to PATH”否则后续在命令行里输入 python 会提示找不到命令macOS 用户可以直接安装官网的 pkg 包也可以使用 Homebrew 安装。安装完成后在终端Windows 上是 CMD 或 PowerShellmacOS / Linux 上是 Terminal输入python --version如果正常输出类似Python 3.12.4的版本号说明安装成功。2.2 使用 pip 安装爬虫常用库Python 的第三方库需要通过 pip 安装。pip 是 Python 自带的包管理工具安装完 Python 后会自动带上。以下库是入门爬虫最常用到的pip install requests pip install beautifulsoup4 pip install lxml pip install pandas这四条命令分别安装requests发送 HTTP 请求的库用于获取网页内容beautifulsoup4HTML 解析库用于从网页中提取数据lxml解析器解析速度比 Python 自带的 html.parser 更快配合 BeautifulSoup 使用pandas数据处理库方便把抓取到的数据保存为 Excel 或 CSV 文件。如果你使用的是 Anaconda 或 Miniconda也可以通过 conda 安装这些库效果相同。2.3 选择开发工具两个最常见的选择是 VS Code 和 PyCharm。VS Code轻量、启动快安装 Python 扩展后即可使用非常适合初学者PyCharm Community 版是 JetBrains 推出的免费版本对 Python 项目的管理更直观调试功能强大。两者任选其一即可。代码运行方式为在 IDE 中写好.py文件点击运行按钮或者在终端执行python 文件名.py其中“文件名.py”要替换成你实际保存的脚本文件名。2.4 验证环境是否就绪为了确认环境没问题可以先写一个最小的测试脚本文件名为test_env.pyimport requests from bs4 import BeautifulSoup print(requests 版本:, requests.__version__) print(环境准备成功)运行后如果没有报错说明 requests 和 BeautifulSoup 都安装成功了。到这里环境准备部分就完成了。3. 爬虫核心原理与 requests 基础3.1 一次网页请求的完整过程在写爬虫之前先理解浏览器打开网页时发生了什么。当你在浏览器地址栏输入一个网址并回车浏览器会完成以下操作解析域名找到服务器对应的 IP 地址向服务器发送 HTTP 请求服务器处理请求后返回 HTML 内容浏览器把 HTML 渲染成可视化的页面。爬虫程序做的就是第 1 到 3 步获取服务器返回的 HTML 内容然后自己解析出需要的数据。它跳过了“渲染”这一步这也是爬虫比浏览器更快的原因之一。3.2 requests 发起 GET 请求requests库的核心功能就是模拟浏览器发送 HTTP 请求。先来看一个最简单的 GET 请求import requests url http://quotes.toscrape.com/ response requests.get(url) print(状态码:, response.status_code) print(响应内容前500个字符:) print(response.text[:500])quotes.toscrape.com是一个专门用于爬虫学习的公开测试网站页面内容安全适合初学者练习。这里解释一下代码response.status_code是 HTTP 状态码200 表示成功403 表示服务器拒绝访问404 表示页面不存在response.text是服务器返回的 HTML 文本内容。如果状态码是 200说明请求成功接下来就可以从response.text中解析数据了。3.3 请求头与 User-Agent 的作用如果你尝试直接用上面的代码请求一些大型网站很可能会收到 403。原因很简单服务器发现请求不是来自浏览器而是来自脚本。浏览器在请求时会携带请求头Headers其中有一个叫User-Agent的字段用来标识客户端的类型。Python 的 requests 默认 UA 是类似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 http://quotes.toscrape.com/ response requests.get(url, headersheaders) print(状态码:, response.status_code)设置 User-Agent 只是最基础的反爬应对手段后面第八部分会系统介绍常见的反爬机制和对应策略。3.4 POST 请求与表单提交GET 请求用于获取数据POST 请求则通常用于提交数据比如登录表单、搜索请求。requests 发送 POST 请求的方法是import requests url http://quotes.toscrape.com/login data { username: test, password: test } response requests.post(url, datadata) print(状态码:, response.status_code)在实际爬虫项目中POST 请求还需要结合浏览器的开发者工具F12来分析具体的提交参数。这里先了解基本语法即可。3.5 处理响应编码问题有时候抓取下来的中文内容显示为乱码这通常是编码问题。服务器返回的 HTML 中会声明字符编码例如charsetutf-8但 requests 默认的编码推断有时并不准确。解决方法是手动指定编码import requests response requests.get(http://quotes.toscrape.com/) response.encoding utf-8 print(response.text[:500])如果页面是 GBK 编码常见于国内的部分旧网站可以设置response.encoding gbk。判断编码的通用思路是先看 HTML 头部meta标签中的 charset 声明再结合响应内容实际情况调整。4. 数据解析从 HTML 中提取有用信息拿到 HTML 内容之后下一步是解析。常见的解析方式有三种正则表达式、BeautifulSoup、XPath。三者的定位不同实际项目中通常会组合使用。4.1 正则表达式re 模块正则表达式是一种描述字符串匹配模式的语法。它是解析文本的利器但不是解析 HTML 的首选因为 HTML 结构复杂正则表达式写起来容易出错可读性也差。不过了解它是必要的因为在某些场景下比如从 JavaScript 代码中提取 JSON 数据、从一段文本中提取日期和邮箱正则表达式效率很高。下面是从一段 HTML 中提取标题的示例import re html titleQuotes to Scrape/titleh1Quotes/h1 title re.search(rtitle(.*?)/title, html) print(title.group(1))输出结果为Quotes to Scrape。其中(.*?)是非贪婪匹配表示匹配尽可能少的内容group(1)取出第一个括号中匹配到的部分。关于正则表达式的更多语法建议单独学习它是独立于爬虫的一项通用技能。4.2 BeautifulSoup 基础用法BeautifulSoup 是目前初学者最友好的 HTML 解析库。它能自动补全残缺的 HTML 结构并提供简单直观的查找方法不需要编写复杂的正则表达式。先看基本用法from bs4 import BeautifulSoup html div classquote span classtextThe world as we have created it is a process of our thinking./span span classauthorAlbert Einstein/span /div soup BeautifulSoup(html, html.parser) # 查找第一个符合条件的标签 quote soup.find(div, class_quote) text quote.find(span, class_text).text author quote.find(span, class_author).text print(名言:, text) print(作者:, author)关键点解释BeautifulSoup(html, html.parser)表示使用 Python 自带的解析器soup.find(div, class_quote)查找第一个class属性为quote的 div 标签注意是class_后面有下划线因为class是 Python 的关键字.text获取标签内的文本内容。如果要查找所有符合条件的标签使用find_allall_quotes soup.find_all(div, class_quote) print(共找到, len(all_quotes), 条名言)4.3 CSS 选择器与 select 方法BeautifulSoup 还支持通过 CSS 选择器定位元素使用select方法。对于熟悉 CSS 的开发者来说这种方式更简洁。soup BeautifulSoup(html, html.parser) # 等价于 soup.find(span, class_text) text soup.select_one(span.text).text # 等价于 soup.find_all(div, class_quote) quotes soup.select(div.quote)select_one返回第一个匹配的元素select返回所有匹配元素的列表。CSS 选择器常用语法包括写法含义div.quoteclass 属性包含 quote 的 div 标签#contentid 为 content 的标签a[href]带 href 属性的 a 标签div pdiv 直接子元素中的 p 标签4.4 XPath 与 lxmlXPath 是另一种在 XML/HTML 文档中查找信息的语言lxml 库支持使用 XPath 语法。如果你之前在爬虫教程中看到过//div[classquote]这样的写法那就是 XPath。from lxml import html page html.fromstring(html) quotes page.xpath(//div[classquote]) text quotes[0].xpath(.//span[classtext]/text()) print(text)//div[classquote]表示在整个文档中查找 class 属性为 quote 的 div 标签。./span[classtext]/text()表示在当前节点下查找符合条件的 span 标签并取出其中的文本。XPath 的特点是表达能力强、解析速度较快适合复杂的层级结构查找。Scrapy 框架默认内置 XPath 支持所以学好 XPath 对后续进阶很有帮助。4.5 三种解析方式的选择建议解析方式优点缺点适用场景正则表达式灵活适合文本提取写复杂规则难维护提取特定格式文本、JSON 数据BeautifulSoup易上手容错性强解析速度一般初学者首选、中小型项目XPath lxml查找能力强大速度快语法需要额外学习复杂结构解析、Scrapy 框架开发在实际项目中推荐优先掌握 BeautifulSoup 和 XPath 两种方法正则表达式在特定场景下作为补充工具使用。5. 完整实战案例抓取名言网站并保存数据前面几章讲解了基础概念和环境这一节我们做一个真实的项目。目标抓取quotes.toscrape.com首页和分页中的名言、作者、标签数据并保存为 CSV 文件。5.1 分析网页结构在动手写代码之前先分析目标网页的结构。打开http://quotes.toscrape.com/在页面上按 F12 打开开发者工具用选择器点击页面中的名言区域。你会发现每条名言的结构如下div classquote span classtextThe world as we have created it is a process of our thinking./span span by small classauthorAlbert Einstein/small a href/author/Albert-Einstein(about)/a /span div classtags a classtag href/tag/change/page/1/change/a a classtag href/tag/deep-thoughts/page/1/deep-thoughts/a /div /div我们要提取的内容是span.text中的名言文本small.author中的作者名div.tags下面所有a.tag标签的文本作为标签列表。分页规律也需要确认。点击页面底部的 Next 按钮观察 URL 变化。这个网站的翻页格式是http://quotes.toscrape.com/page/2/、page/3/以此类推。5.2 编写完整爬虫代码创建一个文件quotes_spider.py写入以下代码import csv import time import requests from bs4 import BeautifulSoup def fetch_page(page_num): 获取指定页码的 HTML 内容 url fhttp://quotes.toscrape.com/page/{page_num}/ 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) if response.status_code 200: response.encoding utf-8 return response.text print(f第 {page_num} 页请求失败状态码: {response.status_code}) return None def parse_page(html): 从 HTML 中提取名言数据 soup BeautifulSoup(html, html.parser) quotes [] for item in soup.select(div.quote): text item.select_one(span.text).text author item.select_one(small.author).text tags [tag.text for tag in item.select(a.tag)] quotes.append({ text: text, author: author, tags: 、.join(tags) }) return quotes def save_to_csv(all_quotes): 保存数据到 CSV 文件 with open(quotes.csv, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[text, author, tags]) writer.writeheader() writer.writerows(all_quotes) def main(): all_quotes [] for page_num in range(1, 11): print(f正在抓取第 {page_num} 页...) html fetch_page(page_num) if html is None: break # 如果页面中没有名言内容说明已经到最后一页 if 没有找到内容 in html or quote not in html: break page_quotes parse_page(html) all_quotes.extend(page_quotes) time.sleep(1) # 每页间隔 1 秒避免请求过快 save_to_csv(all_quotes) print(f抓取完成共保存 {len(all_quotes)} 条数据) if __name__ __main__: main()这段代码的构成如下fetch_page负责发送请求带有超时时间和 User-Agentparse_page使用 BeautifulSoup 解析页面中的名言、作者和标签save_to_csv使用 csv 模块把数据写入文件encodingutf-8-sig可以防止 Excel 打开 CSV 时出现中文乱码main函数控制分页循环每抓完一页休息 1 秒尽量不给目标服务器造成压力。5.3 运行与预期结果在终端执行python quotes_spider.py正常情况下输出会类似正在抓取第 1 页... 正在抓取第 2 页... ... 正在抓取第 10 页... 抓取完成共保存 100 条数据同时目录下会生成一个quotes.csv文件用 Excel 打开可以看到每一行的内容分别是名言文本、作者和标签列表。如果第一次运行有报错保留报错信息对照后面的“常见问题与排查思路”部分逐一检查。5.4 分页与全站抓取的优化思路上面的示例固定抓取前 10 页。实际上更通用的做法是判断“是否有下一页”来决定是否继续抓取。这里提供一种优化思路在解析页面时同时检查是否存在li.next a这样的标签。next_link soup.select_one(li.next a) if next_link is None: print(没有下一页抓取结束) break这样就能实现自动感知翻页不需要手动指定页数。类似的逻辑也适用于其他网站但具体选择器需要根据目标网页结构调整。6. 常见反爬机制与应对策略前面提到很多网站会检测爬虫行为并做出限制。这一节系统地梳理常见的反爬机制以及对应的合法应对方式。6.1 User-Agent 检测这是最基础的反爬手段。服务器检查请求头中的 User-Agent如果是明显的爬虫标识如python-requests直接拒绝请求。应对方式是在请求头中添加真实浏览器的 User-Agent。上面的实战案例已经演示了这种方法。更进一步的做法是准备多个不同的 UA每次请求随机切换减少同质化特征。6.2 请求频率限制服务器会统计同一 IP 在单位时间内的请求次数。如果短时间内请求频率远超人类正常访问速度会触发限制最常见的表现是返回 403 或要求验证码。合法的应对方式是控制抓取频率。最简单的做法是在每次请求之间加入随机延时import time import random time.sleep(random.uniform(1, 3))这样每次请求之间的间隔在 1 到 3 秒之间随机抖动符合正常浏览的行为特征。6.3 IP 封禁与代理如果某一个 IP 的请求频率过高服务器可能直接封禁该 IP导致所有后续请求都被拒绝。对于需要大量请求的场景可以使用代理 IP 池把请求分散到不同的 IP 上。requests 使用代理的方式是proxies { http: http://127.0.0.1:7890, https: http://127.0.0.1:7890 } response requests.get(url, proxiesproxies)需要注意的是使用代理时要确保代理来源合法不要使用来路不明的代理服务否则会有隐私和安全隐患。6.4 动态渲染页面有些网站的数据不是直接写在 HTML 中而是通过 JavaScript 动态加载的。requests 只能获取到最初的 HTML 源码拿不到 JavaScript 执行后生成的内容。常见的应对方案有两种第一种是寻找页面背后的 API 接口。打开浏览器的开发者工具切到 Network 面板刷新页面观察 XHR 或 Fetch 请求。很多时候数据是通过 JSON 接口返回的直接请求接口的效率远高于渲染完整页面。第二种是使用浏览器自动化工具如 Selenium 或 Playwright。它们会启动一个真实的浏览器内核执行 JavaScript 后拿到渲染完成的页面。缺点是速度慢、资源占用高。示例代码如下from selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() options.add_argument(--headlessnew) driver webdriver.Chrome(optionsoptions) driver.get(http://quotes.toscrape.com/js/) html driver.page_source print(html[:500]) driver.quit()这段代码使用无头浏览器headless模式打开一个动态页面然后获取渲染后的 HTML。6.5 验证码与登录限制当网站出现验证码或强制登录要求时说明目标站点对数据访问有严格的权限控制。对于这种情况正确的做法是优先查看网站是否提供官方 API在授权范围内进行数据获取不推荐尝试绕过验证码或暴力爬取这既不稳定也有法律风险。记住一个原则爬虫的价值在于自动化处理公开数据而不是破解访问控制。如果某个数据需要登录才能查看默认情况下它就不属于公开数据使用前需要确认自己是否有权限。7. Scrapy 框架与分布式爬虫入门在 requests 写多了之后你会发现它存在一些不舒服的地方请求逻辑和解析逻辑都写在一个文件里代码一多就难以维护无法方便地处理并发请求没有统一的调度机制。Scrapy 就是为解决这些问题而生的框架。7.1 Scrapy 的架构Scrapy 是一个 Python 爬虫框架核心组件包括Scheduler 调度器管理待抓取的请求队列Downloader 下载器负责发送请求并获取响应Spiders 爬虫编写页面解析逻辑Item Pipeline 管道负责数据清洗、去重和存储Middlewares 中间件在请求和响应阶段进行拦截常用于设置代理、修改请求头等。整个流程可以理解为调度器把请求交给下载器下载器取回响应后交给爬虫解析解析出的数据经过管道处理最终存储。7.2 创建一个 Scrapy 项目需要先安装pip install scrapy然后在命令行中执行scrapy startproject quotes_project cd quotes_project scrapy genspider quotes quotes.toscrape.com生成的项目结构如下quotes_project/ scrapy.cfg quotes_project/ __init__.py items.py middlewares.py pipelines.py settings.py spiders/ __init__.py quotes.py在spiders/quotes.py中编写解析逻辑import scrapy class QuotesSpider(scrapy.Spider): name quotes allowed_domains [quotes.toscrape.com] start_urls [http://quotes.toscrape.com/] def parse(self, response): for quote in response.css(div.quote): yield { text: quote.css(span.text::text).get(), author: quote.css(small.author::text).get(), } next_page response.css(li.next a::attr(href)).get() if next_page: yield response.follow(next_page, callbackself.parse)运行爬虫scrapy crawl quotes -o quotes.json运行之后会在项目目录下生成quotes.json文件里面是抓取到的名言和作者数据。Scrapy 的优势在这里体现得很明显不需要手动管理分页 URL不需要自己写 CSV 保存逻辑-o参数直接支持输出为 JSON、CSV、XML 等格式。框架内置了去重机制和请求调度代码结构也更清晰。7.3 分布式爬虫的简单理解当爬虫需要抓取的页面达到百万级时单台服务器的带宽和请求速度会成为瓶颈这时候就需要分布式爬虫。分布式爬虫的核心思路是多个节点共享同一个请求队列各自负责一部分抓取任务然后把数据汇总。常见的实现方式是借助 Redis 保存待抓取的 URL各个爬虫节点从 Redis 中领取任务。Scrapy 配合 Scrapy-Redis 是经典组合。这一节不展开深入代码只先建立概念。分布式爬虫属于进阶方向等能熟练使用 Scrapy 之后再学习效果更好。7.4 requests 与 Scrapy 如何选择维度requestsScrapy学习成本低较高适合规模小型项目、一次性抓取中型以上、需要长期维护并发能力需要手动实现自带并发调度扩展性一般强中间件、管道机制完善调试方式简单直接需要了解框架运行机制我的建议是入门阶段先用 requests 写小脚本理解爬虫的核心逻辑等场景变复杂、数据量变大后再切换到 Scrapy。8. 常见问题与排查思路下面汇总爬虫学习过程中最常遇到的几类问题。如果程序运行时报错不要急着查网上的零散帖子先对照这个表格定位。问题现象常见原因解决思路请求返回 403缺少请求头或 User-Agent 被识别添加模拟浏览器的 headers返回内容乱码编码识别错误设置response.encoding utf-8或对应的 charset找不到目标元素解析结果为空选择器写错或数据是动态加载检查 HTML 中标签和 class 是否匹配考虑接口或 Selenium连接超时网络不稳定或目标服务器响应慢增加 timeout 参数配合 try-except 和重试请求几次后被封 IP请求频率过高增加延时、使用代理池、控制并发数pip 安装库失败网络问题或源不稳定切换为国内镜像源安装Python 提示找不到模块库没有安装到当前环境检查是否使用了虚拟环境执行pip list确认8.1 403 Forbidden 的排查步骤403 是整个爬虫学习中概率最高的报错。遇到它时按下面的顺序排查清空所有自定义 headers只用 requests.get 默认参数请求如果返回 200说明问题出在请求头中添加 User-Agent看是否能解决问题如果仍然 403检查目标网站是否对 Cookie、Referer 等字段有要求考虑是 IP 被限制还是请求频率过高切换网络环境或降低频率测试。8.2 解析结果为空的常见原因写好了选择器返回的列表却是空的。这种情况通常有三个原因第一目标网站的数据不是静态 HTML而是通过 Ajax 请求动态加载的。这时需要查看 XHR 接口直接请求接口地址。第二HTML 结构和预期不一致。有时候浏览器开发者工具中显示的结构和 requests 获取到的结构并不相同因为浏览器默认执行了 JavaScript 渲染。解决方法是打印response.text前 500 个字符确认实际拿到的内容。第三class 名称中包含空格或多个类名。比如classquote left使用class_quote是匹配不到的需要改为soup.find(div, class_quote left)或使用 CSS 选择器div.quote.left。9. 最佳实践与工程化建议学习爬虫不能止步于“能跑通”更重要的是写出健壮、可维护、合规的代码。以下是实际项目中踩过坑之后总结的经验。9.1 请求层做好异常处理与重试网络环境不稳定是常态爬虫必须做好容错。不要写一遇到异常程序就崩溃的代码而应该捕获异常并做有限次数的重试。下面是一个带重试机制的请求函数示例import time import requests from requests.exceptions import RequestException def fetch_with_retry(url, headers, max_retry3): for i in range(max_retry): try: response requests.get(url, headersheaders, timeout10) if response.status_code 200: return response except RequestException as e: print(f第 {i 1} 次请求失败: {e}) time.sleep(2) return None在重试之间加入延时避免给服务器造成压力。9.2 严格遵守 robots.txt 与访问频率robots.txt 是网站告诉爬虫“哪些页面可以抓、哪些不可以抓”的协议文件。通常在域名根路径下可以访问到例如http://quotes.toscrape.com/robots.txt。在正式编写爬虫之前先查看目标网站的 robots.txt遵守其中声明的规则。同时抓取时需要控制并发数和请求频率。一个简单的参考标准是普通网站每秒最多 1 到 2 个请求小网站需要更保守。9.3 数据清洗与去重爬虫抓下来的数据往往是杂乱无章的需要通过管道进行清洗比如去除空白字符、处理缺失字段、转换数据类型。去重也是一个重要问题。同样的数据被重复抓取后保存到数据库前应该通过唯一标识字段判断是否存在。可以使用数据库的唯一索引或者在代码层使用集合记录已经见过的 URL。下面是一个简单的 URL 去重示例visited_urls set() def should_fetch(url): if url in visited_urls: return False visited_urls.add(url) return True9.4 日志记录与监控爬虫脚本一旦运行起来不能只看终端输出遇到问题回溯时日志非常重要。使用 Python 自带的 logging 模块而不是到处printimport logging logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(spider.log, encodingutf-8), logging.StreamHandler() ] ) logging.info(开始抓取第 1 页) logging.warning(第 2 页请求失败进行重试)有了日志即使程序运行时没有人在旁边盯着后期也能排查出问题。9.5 模块化代码结构爬虫的代码不要都堆在一个文件里。推荐按职责拆分project/ spiders/ quotes_spider.py # 单个爬虫的解析逻辑 parsers/ quote_parser.py # 解析函数 storage/ csv_writer.py # 数据保存 utils/ http_client.py # 请求与重试 logger.py # 日志配置 config.py # 配置项和常量这种结构的好处是换一个目标网站时只需要新增一个解析模块不需要改动底层的请求和存储逻辑。9.6 数据库选型建议对于数据量较小的爬虫项目CSV 文件完全够用读取也方便。数据量增长到数万条以上时建议使用数据库SQLite单文件、轻量适合中小规模数据MySQL / PostgreSQL适合生产环境支持高并发写入和复杂查询MongoDB适合字段结构经常变化的数据文档型存储。写入数据库时要注意使用事务和批量插入减少连接开销。10. 总结与学习路线到这里一条从零开始的 Python 网络爬虫学习路径基本完整了。回顾一下本文的核心内容先理解了爬虫是模拟浏览器自动获取网页数据的程序完成了 Python 和常用第三方库的环境搭建然后掌握了 requests 发送 GET/POST 请求、设置请求头和超时时间的基础用法再使用 BeautifulSoup 和 XPath 从 HTML 中提取目标数据通过一个完整的名言网站案例体验了从页面分析、分页抓取到 CSV 保存的全流程最后了解了反爬机制、Scrapy 框架、分布式爬虫概念以及工程化开发中的最佳实践。对于初学者下一步的学习顺序建议是把本文中的实战案例独立重写一遍确保不参照代码也能完成找一个结构简单的公开静态网站自行设计一个抓取需求并实现学习 JSON 接口抓取理解 Ajax 动态页面的数据加载方式掌握 XPath 语法为学习 Scrapy 打基础尝试使用 Scrapy 重写之前完成的项目体会框架带来的工程化便利学习异步爬虫库如 aiohttp 和 httpx提升大规模抓取时的效率在掌握以上内容后再逐步了解分布式爬虫、增量爬取等进阶话题。在整个学习过程中要养成两个习惯。第一个是每次写爬虫前先确认目标网站的访问条款和 robots.txt只抓取公开的、不涉及隐私的数据。第二个是设置合理的请求频率不要因为抓取行为影响目标网站的正常运行。技术能力越强越需要守住边界。如果觉得这篇文章对你有帮助可以收藏备用。接下来选一个简单的小网站动手写完自己抓到的第一批数据你就会发现爬虫真的没有想象中那么难。
返回列表