公司动态

Python爬虫零基础实战教程:从环境搭建到Scrapy框架完整学习路线

📅 2026/8/29 6:05:07
Python爬虫零基础实战教程:从环境搭建到Scrapy框架完整学习路线
如果你正在找一套能直接从零上手、不绕弯的 Python 爬虫教程这次的内容可以一次看完。这套教程覆盖了 Python 爬虫从环境搭建、请求发送、页面解析、数据存储到动态页面抓取、批量爬虫、增量爬虫、断点续爬和 Scrapy 框架的完整链路。课程面向没有任何编程基础的读者全程用可复现代码讲解不堆概念不念文档重点放在“能不能跑起来”和“出了问题怎么查”。文章会按实际学习顺序拆解先准备 Python 开发环境再写第一个爬虫请求然后用 BeautifulSoup 解析页面接着处理 Ajax 动态加载随后解决数据存储、批量任务、增量抓取和断点续爬最后介绍 Scrapy 框架的启动方式和常见坑。每一步都给到可直接运行的代码示例并标注需要根据目标网站调整的参数位置。在阅读前先提醒一个最重要的前提爬虫技术本身是中性的但使用边界非常明确。本文所有示例仅用于学习和技术验证任何采集行为都必须遵守目标网站的 robots 协议、服务条款和适用的法律法规不得用于窃取隐私、破坏服务、绕过登录或版权保护机制。涉及淘宝、抖音、京东、小红书、企查查等平台的数据时务必先确认是否有官方 API 或授权接口个人测试时也要控制请求频率避免对目标服务器造成压力。下面直接进入正题。1. Python 爬虫核心能力速览能力项说明面向人群零基础入门、刚接触 Python、想系统学习网页数据采集的开发者前置要求会操作电脑能安装软件不需要编程基础核心库requests、BeautifulSoup4、lxml、json、csv、sqlite3、threading、Scrapy主要功能静态网页抓取、动态接口请求、数据清洗、数据存储、批量任务、增量爬虫、断点续爬页面解析方式正则表达式、BeautifulSoup、CSS 选择器、JSON 接口直取数据存储CSV 文件、JSON 文件、SQLite 数据库反爬应对headers 伪装、请求间隔、代理基础用法、cookie 处理扩展能力多线程并发、Scrapy 框架、分布式爬虫运行环境Windows / macOS / Linux 均可Python 3.8 即可硬件要求普通办公电脑即可不需要独立显卡是否支持 API爬虫本身是采集程序后续可封装成 API 服务供其他系统调用是否支持批量任务支持可通过循环、队列和多线程实现批量采集主要风险点版权、隐私、平台条款、访问频率控制从能力表可以看出这套技术栈覆盖了爬虫学习的绝大部分基础场景。核心思路是用 requests 拿到网页或接口数据用 BeautifulSoup 或正则把目标内容提取出来再落盘到文件或数据库。2. 爬虫适用场景与使用边界爬虫不是万能工具也不应该被当成绕过平台规则的“黑科技”。先说清楚适合做什么不适合做什么。适合的场景包括学习 HTTP 请求与网页结构的关系。采集公开的、非敏感、非版权保护的信息例如公开新闻、公开论文元数据、天气数据、股票行情快照。构建个人学习用的数据集。对自有网站或已获授权的网站进行数据备份和监控。研究反爬机制用于自己网站的安全防护测试。不适合或需要谨慎的场景包括需要登录才能查看的数据尤其是涉及个人隐私、订单、通讯录、会员信息的内容。平台明确禁止爬取的页面。包含版权内容如付费文章、独家图片、视频素材的批量下载。高频请求导致目标服务异常。绕过验证码、指纹识别、加密参数的破解行为。另外要特别说明一点robots.txt 是网站声明爬虫访问规则的文件虽然不是法律文件但遵守它是规范爬虫行为的基本要求。正规爬虫项目应该先查看目标网站的 robots.txt确认哪些路径允许抓取。很多大平台都有官方 API优先调用官方接口而不是去逆向网页。把这一点想清楚后面写代码时就知道哪些能写哪些不能碰。3. 环境准备与前置条件爬虫开发环境非常轻量主流配置是 Python 3.8 以上版本加上一个趁手的代码编辑器。这里给出一套通用准备流程适用于 Windows、macOS 和 Linux。3.1 安装 Python 并配置环境变量建议到 Python 官网下载 Python 3.10 或更高版本。Windows 安装时务必勾选“Add Python to PATH”否则命令行会提示找不到 python 命令。macOS 用户可以用 Homebrew 安装Linux 用户可以用 apt 或 yum。安装完成后打开终端或命令提示符执行python --version如果输出类似Python 3.10.x说明安装成功。3.2 换 pip 镜像源国内网络环境下建议把 pip 默认源切换到国内镜像避免下载依赖包时超时。这里以清华源为例在终端执行pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple之后安装 Python 库的速度会明显提升。3.3 安装核心依赖库创建独立目录作为项目空间然后安装爬虫常用的第三方库pip install requests beautifulsoup4 lxml数据存储和并发处理用到的库都是 Python 标准库不需要额外安装csvCSV 文件读写。jsonJSON 数据解析。sqlite3SQLite 数据库操作。threading / concurrent.futures多线程任务。3.4 选择代码编辑器推荐 VS Code轻量且配置简单。安装 Python 扩展后可以直接在编辑器里运行 .py 文件也可以在终端里执行命令。使用 VS Code 时注意右下角解释器版本确保选择的是刚安装的 Python 3.10 环境。还需要了解几个常见知识点虚拟环境可以隔离不同项目的依赖但不是爬虫入门的硬性要求。直接使用全局环境也能跑通。Windows 下如果出现编码问题在代码文件开头加上# -*- coding: utf-8 -*-。如果目标网站是 HTTPSrequests 会自动处理证书校验一般不需要额外配置。4. 经典爬虫流程从请求到响应爬虫的第一步是发送 HTTP 请求并获取响应。这里用 requests 库写一个最小示例目标选择公开的测试站点例如 httpbin.org 或 example.com。生产项目中请替换为已确认可合法采集的地址。4.1 第一次请求import requests url https://httpbin.org/get response requests.get(url, timeout10) print(response.status_code) print(response.text)输出结果中status_code如果是 200说明请求成功response.text是服务器返回的 HTML 或 JSON 内容。4.2 添加请求头很多网站会校验 User-Agent默认的 Python-requests 标识容易被拒绝。模拟浏览器请求头部是爬虫入门必须掌握的操作import requests url https://httpbin.org/headers 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, Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/webp,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9,en;q0.8 } response requests.get(url, headersheaders, timeout10) print(response.status_code)4.3 处理响应编码中文网站常见的编码是 utf-8 和 gbk。如果 response 里的中文变成乱码需要手动指定编码import requests url https://example.com response requests.get(url, timeout10) response.encoding utf-8 print(response.text[:500])如果网站是 gbk 编码就改成response.encoding gbk。4.4 请求超时与异常处理网络请求不稳定必须加超时和异常捕获import requests from requests.exceptions import RequestException url https://httpbin.org/get try: response requests.get(url, timeout(3, 10)) response.raise_for_status() print(response.text) except RequestException as e: print(请求失败:, e)到这里爬虫的请求链路已经打通。判断成功的标准是能拿到 HTTP 200 状态码并且能正常输出目标页面的内容。最常见的失败原因包括没有设置 User-Agent被服务器拒绝。目标网站开启了强制 HTTPS 跳转请求时需要用 https 开头的地址。网络环境无法访问目标域名。服务器返回 403一般需要补充 headers 或 cookie。5. 页面解析正则表达式与 BeautifulSoup拿到 HTML 响应后下一步是把页面里的目标信息提取出来。常用三种方式正则表达式、BeautifulSoup、XPath。对于入门阶段BeautifulSoup 最友好。5.1 使用 BeautifulSoup 解析标题from bs4 import BeautifulSoup html html headtitle测试页面/title/head body div classpost h2第一篇文章标题/h2 a href/post/1阅读全文/a /div div classpost h2第二篇文章标题/h2 a href/post/2阅读全文/a /div /body /html soup BeautifulSoup(html, html.parser) title soup.title.string print(网页标题:, title) posts soup.select(div.post h2) for post in posts: print(post.get_text(stripTrue))这段代码演示了两个关键 APIsoup.title.string获取 title 文本。soup.select(div.post h2)用 CSS 选择器定位所有文章标题。5.2 提取链接和属性for a in soup.select(div.post a): href a.get(href) text a.get_text(stripTrue) print(text, href)5.3 用正则做补充提取正则适合处理文本中的固定模式比如邮箱、手机号、日期等。用 Python 的 re 模块即可import re text 联系邮箱: testexample.com, 备用邮箱: hellotest.org pattern r[a-zA-Z0-9._%-][a-zA-Z0-9.-]\.[a-zA-Z]{2,} emails re.findall(pattern, text) print(emails)5.4 使用 lxml 加速解析BeautifulSoup 默认使用 Python 内置解析器速度尚可。如果解析量大可以指定 lxml 解析器soup BeautifulSoup(html, lxml)lxml 需要额外安装之前已经通过 pip 安装完成。判断解析是否成功的标准是能从页面中准确提取到目标字段并且没有把无关内容一起带出来。如果出现提取内容为空先检查选择器是否正确再看页面是否被反爬拦截。6. 动态页面与 Ajax 接口爬取很多现代网站使用 JavaScript 动态渲染页面直接 requests 拿到的 HTML 里没有目标数据。这时候正确思路不是用 Selenium 硬渲染而是先抓包找数据接口。6.1 抓包定位接口浏览器打开开发者工具F12切换到 Network 面板刷新页面筛选 XHR 请求。找到返回 JSON 数据的请求复制它的 URL。通常这个 URL 就是真正的数据接口。6.2 请求 JSON 接口import requests import json url https://api.example.com/list headers { User-Agent: Mozilla/5.0, Referer: https://example.com/ } response requests.get(url, headersheaders, timeout10) data response.json() for item in data.get(list, [])[:5]: print(item.get(title))6.3 处理分页参数大多数接口分页靠 page 和 page_size 参数for page in range(1, 4): params { page: page, page_size: 20 } response requests.get(url, headersheaders, paramsparams, timeout10) data response.json() print(f第{page}页 获取到 {len(data.get(list, []))} 条数据)判断接口爬取成功的标准是返回的 JSON 结构清晰字段稳定分页逻辑明确。常见的坑包括接口需要签名参数或依赖 cookie。返回数据经过加密需要逆向解密逻辑。这一点如果涉及平台逆向不建议入门阶段触碰也存在法律风险。接口有频率限制大量并发会被封 IP。7. 数据存储CSV、JSON 与 SQLite爬下来的数据不落地就等于白爬。常用的存储方式有 CSV、JSON 和 SQLite 数据库。7.1 写入 CSVimport csv rows [ {title: 文章一, url: https://example.com/post/1}, {title: 文章二, url: https://example.com/post/2} ] with open(output.csv, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[title, url]) writer.writeheader() writer.writerows(rows)编码使用utf-8-sig是为了方便 Excel 直接打开时不乱码。7.2 写入 JSONimport json data [ {title: 文章一, url: https://example.com/post/1}, {title: 文章二, url: https://example.com/post/2} ] with open(output.json, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2)7.3 写入 SQLiteSQLite 适合结构化数据和增量更新场景import sqlite3 conn sqlite3.connect(crawler.db) cursor conn.cursor() cursor.execute( CREATE TABLE IF NOT EXISTS posts ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, url TEXT NOT NULL UNIQUE, created_at TEXT DEFAULT CURRENT_TIMESTAMP ) ) cursor.execute( INSERT OR IGNORE INTO posts (title, url) VALUES (?, ?), (文章一, https://example.com/post/1) ) conn.commit() conn.close()使用INSERT OR IGNORE配合UNIQUE约束是增量爬虫的基础。同一 URL 重复抓取时不会插入重复数据。8. 反爬应对与合规边界很多平台通过 User-Agent、请求频率、IP、cookie、验证码等方式限制爬虫。入门阶段只需要理解并应用合理的应对方式。8.1 请求时间间隔最简单的礼貌抓取方式是设置延时import time import random for page in range(1, 11): print(f抓取第 {page} 页) # 抓取逻辑 time.sleep(random.uniform(1, 3))8.2 cookie 处理部分页面第一次访问会下发 cookie后续接口校验 cookie 中的字段。requests 的 Session 对象可以自动维持 cookieimport requests session requests.Session() session.headers.update({ User-Agent: Mozilla/5.0 }) # 第一次访问获取 cookie session.get(https://example.com, timeout10) # 后续请求自动携带 cookie response session.get(https://example.com/data, timeout10) print(response.text)8.3 代理基础用法高频请求时可能需要使用代理。这里给出 requests 的代理配置模板实际使用需要替换为合法代理资源proxies { http: http://127.0.0.1:7890, https: http://127.0.0.1:7890 } response requests.get(url, headersheaders, proxiesproxies, timeout10)8.4 需要明确避开的坑暴力破解登录接口是违法行为绝对不能碰。破解验证码属于绕过安全防护的行为不讨论。大规模抓取个人隐私数据、订单数据、通讯录数据涉嫌侵犯公民个人信息罪。大量并发请求导致目标服务瘫痪可能涉及破坏计算机信息系统罪。这部分不是套话而是爬虫学习中最容易忽略的部分。判断一个采集行为是否合规可以问自己四个问题数据是否公开是否涉及个人隐私目标网站是否明确禁止爬虫是否会对目标服务器造成异常压力如果任何一个问题的答案是“是”就要停下来重新评估方案。9. 批量爬虫、增量爬虫与断点续爬从热搜词来看批量型爬虫、增量型爬虫、垂直型爬虫是很多读者关心的关键词。这里结合爬虫工程化场景说明它们的区别。9.1 三种爬虫类型批量型爬虫一次性采集某类数据的全量或指定范围例如抓取某站点前 100 页列表。实现方式简单for 循环加延迟即可。增量型爬虫只抓取新增或变化的数据。核心是维护一个“已处理标识”通常用 URL、内容哈希或更新时间判断。增量爬虫适合长期运行的监控场景例如定时检测某网站的公告更新。垂直型爬虫聚焦特定领域的结构化数据例如只抓取电商价格、招聘信息或论文元数据。垂直爬虫的重点是字段抽取准确、解析逻辑稳定。9.2 断点续爬原理与实现批量爬虫最容易遇到的问题是中途中止。网络波动、程序异常、停电都会导致重新开始。断点续爬的本质是在任务进行中记录进度重启后从上次完成的位置继续。记录进度的最简单方式是维护一个 task_state.txtimport json import os STATE_FILE task_state.txt def load_state(): if os.path.exists(STATE_FILE): with open(STATE_FILE, r, encodingutf-8) as f: return json.load(f) return {} def save_state(state): with open(STATE_FILE, w, encodingutf-8) as f: json.dump(state, f, ensure_asciiFalse, indent2) state load_state() start_page state.get(last_page, 1) for page in range(start_page, 11): print(f抓取第 {page} 页) # 抓取并解析后 state[last_page] page save_state(state)更工程化的做法是把解析结果先写入 SQLite使用唯一约束去重同时记录任务进度表。这样即使程序崩溃重启后也能从 SQLite 中判断哪些 URL 已经处理过。9.3 批量任务的日志与重试批量爬虫不能只 print最好记录日志方便定位失败位置import logging logging.basicConfig( filenamecrawler.log, levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s ) try: response requests.get(url, timeout10) response.raise_for_status() logging.info(f抓取成功: {url}) except Exception as e: logging.error(f抓取失败: {url}, 错误: {e})失败重试机制也很重要常见做法是设置重试次数上限import time def fetch_with_retry(url, max_retries3): for attempt in range(max_retries): try: response requests.get(url, timeout10) response.raise_for_status() return response except Exception as e: print(f第 {attempt 1} 次请求失败: {e}) if attempt max_retries - 1: time.sleep(2) return None10. 多线程并发与请求频率控制爬虫速度慢很多人第一反应是开多线程。但并发数过高会导致被封 IP也可能给目标服务器造成压力。入门阶段要先学会控制并发而不是盲目拉满。10.1 使用 ThreadPoolExecutorfrom concurrent.futures import ThreadPoolExecutor, as_completed import requests import time urls [fhttps://httpbin.org/get?id{i} for i in range(10)] def fetch(url): response requests.get(url, timeout10) return url, response.status_code with ThreadPoolExecutor(max_workers3) as executor: future_map {executor.submit(fetch, url): url for url in urls} for future in as_completed(future_map): url, status future.result() print(url, status)10.2 控制请求速率即使有线程池也要在任务之间加入间隔。常见的做法是使用队列和延迟import queue import threading import time q queue.Queue() for i in range(10): q.put(fhttps://httpbin.org/get?id{i}) def worker(): while not q.empty(): url q.get() print(处理:, url) time.sleep(1) q.task_done() threads [threading.Thread(targetworker) for _ in range(2)] for t in threads: t.start() for t in threads: t.join()判断并发是否合理的标准很简单如果目标网站开始返回 429 或 403说明并发过高需要降低 worker 数量并加大间隔。11. Scrapy 框架快速上手当爬虫规模变大、需要多级页面采集和稳定调度时可以从 requests 切换到 Scrapy。Scrapy 是成熟的爬虫框架自带请求调度、去重、下载器和 Item Pipeline。11.1 安装和创建项目pip install scrapy scrapy startproject myproject cd myproject11.2 创建爬虫scrapy genspider example_spider example.com生成的爬虫文件位于myproject/spiders/example_spider.py基本结构如下import scrapy class ExampleSpider(scrapy.Spider): name example_spider allowed_domains [example.com] start_urls [https://example.com/] def parse(self, response): for item in response.css(div.post): yield { title: item.css(h2::text).get(), url: item.css(a::attr(href)).get() }11.3 运行爬虫scrapy crawl example_spider -o output.jsonscrapy 会自动遵守 robots.txt默认开启如果不希望被某些规则限制可以在 settings.py 中显式设置有依据的配置但更推荐保持默认从源头保证合规。Scrapy 的学习曲线比 requests 陡但做批量任务和长期维护时效率更高。12. 常见问题与排查方法问题现象可能原因排查方式解决方案安装 Python 库失败网络问题或 pip 源不可用查看报错信息切换 pip 镜像源命令行找不到 python未加入 PATH 或环境变量冲突执行python --version重装 Python 并勾选 Add to PATH请求返回 403缺少 User-Agent 或 cookie查看响应头添加浏览器 headers返回内容乱码编码识别错误打印response.encoding手动指定 utf-8 或 gbk爬取结果为空页面是动态渲染或选择器错误查看页面源码是否有目标内容改用接口爬取或修正选择器请求被拒绝IP 被临时限制检查返回状态码降低频率或使用合法代理数据重复未做去重检查数据库唯一约束使用 URL 去重或 INSERT OR IGNORE批量任务中断网络波动或程序异常查看日志实现断点续爬和失败重试编码写入 CSV 乱码编码格式不对检查文件编码使用 utf-8-sig连接超时目标服务器响应慢查看 DNS 和网络增加 timeout 并重试13. 最佳实践与学习建议爬虫学习的关键不只是写几个能跑的脚本而是建立一套稳定的采集工程体系。这里给几条实战经验。第一次跑代码时先小范围测试。比如列表页只抓 2 页字段只输出到终端确认结构没问题后再写文件和数据库。直接跑全量会导致错误被放大定位困难。项目目录按输入、输出、日志分离。数据解析和存储逻辑尽量写成函数便于复用。批量任务加入日志和失败重试机制已经是爬虫工程的底线。接口服务或长期运行的爬虫必须控制访问范围。可以把服务绑定到 127.0.0.1不监听公网地址。涉及需要登录的账号信息不能写死在公开仓库里。数据采集完成后要关注数据的后续使用。如果采集的文章、图片、视频用于重新发布可能涉及版权问题。爬虫只是个取数工具取完数之后怎么用才是风险最大的环节。对学习路线做个提炼requests 加 BeautifulSoup 入门是第一步能解决静态网页问题然后是分析 Ajax 接口和 JSON 解析解决动态页面问题再往后是数据存储和增量爬虫解决工程化问题最后再考虑 Scrapy 或多线程。这个顺序最稳。14. 总结与下一步这套 Python 爬虫教程最值得先跑通的是 requests 加 BeautifulSoup 这一条主线。先能拿到网页、解析出数据、存到文件再考虑更高阶的动态接口和批量任务。最容易踩的坑集中在环境配置、编码问题和反爬拦截上环境装好后先跑 httpbin 这类测试站点不要一上来就抓大平台。下一阶段可以做的扩展方向有三个一是把爬虫改造成定时任务实现增量抓取和断点续爬二是把采集结果封装成 API 服务供其他系统调用三是深入 Scrapy处理更复杂的层级页面和分布式任务。建议收藏备用先把第一段测试请求跑通后面就顺了。