Python爬虫:从入门到高效实战
Python爬虫核心流程包括请求、响应、解析、存储和反爬突破。常用库按功能分类解析: HTTP请求库 requests:同步请求库,语法简洁,支持GET/P请求、POST提交表单、设置请求头等,适合静态页面爬取。 aiohttp:异步请求库,支持高并发并发请求,适合批量爬取数据,提升效率。 数据解析库 Beautiful Soup:HTML解析神器,提供find、find_all等友好API,适合
Python 爬虫的核心流程可拆解为 “发起请求→获取响应→解析数据→存储数据→反爬突破”,不同库对应流程中的不同环节。以下按 “功能分类” 详细解析常用库的定位、作用、关键用法及实战落地,附完整技术选型逻辑:
一、核心基础:HTTP 请求库(发起请求的 “敲门砖”)
爬虫的第一步是向目标服务器发送 HTTP 请求(如 GET/POST),获取页面 HTML 或 API 响应,核心库为 requests 和 aiohttp。
1. requests(同步请求库,爬虫入门首选)
-
核心定位:Python 生态最流行的同步 HTTP 请求库,封装了底层的 TCP/IP 通信,支持 GET/POST、Cookie、代理、SSL 等所有 HTTP 特性,语法极简。
-
核心作用:替代 Python 原生的
urllib
库,解决 “发起请求复杂、代码冗余” 的问题,快速获取静态页面(HTML)或 API 的 JSON 响应。 -
关键知识点:
- 基础请求:
requests.get(url, params, headers, cookies)
(GET 请求带参数)、requests.post(url, data, json)
(POST 提交表单 / JSON)。 - 响应处理:
response.text
(获取 HTML 文本)、response.json()
(解析 JSON 响应)、response.status_code
(判断请求是否成功,200 = 成功)。 - 反爬基础:设置
headers
(模拟浏览器,如 User-Agent)、proxies
(配置代理 IP)、timeout
(设置超时避免卡壳)。
- 基础请求:
-
实战应用(电商商品列表爬取):
import requests # 1. 目标URL(电商商品列表页,带分页参数) url = "https://example-mall.com/api/goods" params = {"page": 1, "category": "laptop"} # 分页+分类参数 # 2. 模拟浏览器请求头(反爬:避免被识别为爬虫) headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/129.0.0.0 Safari/537.36", "Referer": "https://example-mall.com/" # 模拟从首页跳转 } # 3. 发起GET请求 response = requests.get(url, params=params, headers=headers, timeout=10) # 4. 处理响应(若为API,直接解析JSON;若为HTML,交给解析库) if response.status_code == 200: goods_data = response.json() # API响应解析为JSON print(f"第1页商品数:{len(goods_data['list'])}") else: print(f"请求失败:{response.status_code}")
2. aiohttp(异步请求库,高并发爬取首选)
-
核心定位:基于
asyncio
的异步 HTTP 请求库,支持 “多请求并发”,解决 requests “同步阻塞”(一次只能发一个请求)的效率问题,适合批量爬取大量 URL(如爬取 100 页商品,异步比同步快 10 倍以上)。 -
核心作用:在 “高并发场景”(如爬取整站数据、批量检测 URL)中提升效率,避免单线程等待导致的时间浪费。
-
关键知识点:
- 语法依赖
async/await
(Python 异步语法),需用async def
定义异步函数。 - 核心对象:
aiohttp.ClientSession()
(会话对象,复用 TCP 连接,减少开销)。 - 避免 “并发过载”:用
asyncio.Semaphore
控制并发数(如限制 50 个并发,避免压垮目标服务器)。
- 语法依赖
-
实战应用(批量爬取 10 页商品 API):
import aiohttp import asyncio async def fetch_page(session, page): """异步获取单页商品数据""" url = "https://example-mall.com/api/goods" params = {"page": page, "category": "laptop"} headers = {"User-Agent": "Mozilla/5.0 ..."} async with session.get(url, params=params, headers=headers) as response: if response.status == 200: return await response.json() # 异步解析JSON return None async def main(): """主异步函数:控制并发爬取10页""" async with aiohttp.ClientSession() as session: # 限制并发数为5(避免被反爬) semaphore = asyncio.Semaphore(5) # 生成1-10页的任务列表 tasks = [fetch_page(session, page) for page in range(1, 11)] # 并发执行所有任务 results = await asyncio.gather(*tasks) # 处理结果 for page, result in enumerate(results, 1): if result: print(f"第{page}页:{len(result['list'])}个商品") if __name__ == "__main__": asyncio.run(main()) # 启动异步事件循环
二、数据解析库(从响应中 “提取宝藏”)
获取响应后(HTML/JSON/ 文本),需提取目标数据(如商品名称、价格、URL),核心工具分 3 类:HTML 解析库(Beautiful Soup、lxml)、正则库(re)、JSON 解析(内置 json 模块)。
1. Beautiful Soup(BS4,HTML 解析入门首选)
-
核心定位:HTML/XML 解析库,封装了复杂的 HTML DOM 树遍历逻辑,提供 “人类友好” 的 API(如
find
、find_all
),无需懂 HTML 底层结构,即可快速提取数据。 -
核心作用:解决 “手动遍历 HTML 标签繁琐” 的问题,适合解析结构相对规整的静态 HTML(如博客、新闻列表、电商商品页)。
-
关键知识点:
- 解析器选择:优先用
lxml
解析器(速度快、容错性强),需先安装lxml
库(pip install lxml
);次选 Python 内置的html.parser
(无需额外安装,速度慢)。 - 核心方法:
soup.find(tag, attrs)
:提取单个符合条件的标签(如find("div", class_="product-name")
,注意class_
带下划线,避免与 Python 关键字冲突)。soup.find_all(tag, attrs)
:提取所有符合条件的标签(返回列表,如find_all("li", class_="product-item")
)。- 数据提取:
tag.text
(获取标签内纯文本)、tag["href"]
(获取标签属性值,如链接)。
- 解析器选择:优先用
-
实战应用(解析电商商品列表 HTML):
from bs4 import BeautifulSoup import requests # 1. 用requests获取HTML url = "https://example-mall.com/goods/laptop" response = requests.get(url, headers={"User-Agent": "Mozilla/5.0 ..."}) # 2. 用BS4解析HTML(指定lxml解析器) soup = BeautifulSoup(response.text, "lxml") # 3. 提取所有商品项(li标签,class为product-item) product_list = soup.find_all("li", class_="product-item") # 4. 遍历提取每个商品的名称和价格 for product in product_list: # 提取商品名称(h3标签,class为product-name) name = product.find("h3", class_="product-name").text.strip() # 提取商品价格(span标签,class为current-price) price = product.find("span", class_="current-price").text.strip() # 提取商品链接(a标签的href属性) link = product.find("a")["href"] print(f"名称:{name} | 价格:{price} | 链接:{link}")
2. lxml(高性能 HTML 解析库,xpath 核心依赖)
-
核心定位:高性能 HTML/XML 解析库(C 语言编写),速度是 Beautiful Soup 的 5-10 倍,同时支持XPath 语法(一种强大的 XML/HTML 路径查询语言),适合解析复杂结构或大规模 HTML。
-
核心作用:解决 “BS4 速度慢” 和 “复杂标签层级提取难” 的问题,尤其适合需要精准定位深层标签的场景(如
//div[@id="main"]/ul/li/div[2]/span
)。 -
关键知识点:
- XPath 语法:用路径表达式定位标签,核心规则:
//
:从根节点开始,匹配所有符合条件的标签(不考虑层级)。@
:获取标签属性(如//a/@href
获取所有 a 标签的 href 属性)。text()
:获取标签内文本(如//h3/text()
获取所有 h3 标签的文本)。- 条件筛选:
//div[@class="product-item" and @data-id="123"]
(匹配 class 为 product-item 且 data-id 为 123 的 div)。
- lxml 用法:
etree.HTML(html_text)
将 HTML 文本转为可 xpath 查询的对象,tree.xpath(xpath_expr)
执行查询(返回列表)。
- XPath 语法:用路径表达式定位标签,核心规则:
-
实战应用(用 xpath 提取商品数据):
from lxml import etree import requests # 1. 获取HTML url = "https://example-mall.com/goods/laptop" response = requests.get(url, headers={"User-Agent": "Mozilla/5.0 ..."}) # 2. 转为lxml可解析的对象 tree = etree.HTML(response.text) # 3. 用xpath提取所有商品的名称、价格、链接 names = tree.xpath('//li[@class="product-item"]/h3/text()') # 商品名称 prices = tree.xpath('//li[@class="product-item"]//span[@class="current-price"]/text()') # 价格 links = tree.xpath('//li[@class="product-item"]/a/@href') # 链接 # 4. 打包输出 for name, price, link in zip(names, prices, links): print(f"名称:{name.strip()} | 价格:{price.strip()} | 链接:{link}")
3. re(正则表达式库,复杂文本提取工具)
-
核心定位:Python 内置的正则表达式库,用于匹配 “有固定格式的文本”(如 IP 地址、手机号、URL、提取 HTML 中隐藏的接口地址),不依赖 HTML 结构,适合 “非结构化文本” 或 “HTML 解析库无法处理的场景”。
-
核心作用:解决 “HTML 解析库无法提取非标签内的文本” 问题,如从 JavaScript 代码中提取接口 URL(如
var apiUrl = "https://example.com/api";
)、从日志中提取 IP 地址。 -
关键知识点:
- 核心方法:
re.compile(pattern)
:编译正则表达式(重复使用时提升效率)。re.findall(pattern, text)
:提取所有符合 pattern 的文本(返回列表)。re.search(pattern, text)
:匹配第一个符合条件的文本(返回 match 对象,需用group()
获取值)。
- 常用 pattern 示例:
- 提取 URL:
r'https?://[^\s"\']+'
。 - 提取 IP:
r'\b(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b'
。
- 提取 URL:
- 核心方法:
-
实战应用(从 JS 代码中提取 API 地址):
import re import requests # 1. 获取包含JS代码的HTML url = "https://example-mall.com/goods/laptop" response = requests.get(url, headers={"User-Agent": "Mozilla/5.0 ..."}) # 2. 用正则提取JS中的API地址(假设API格式为var api = "https://xxx/api/goods?page=1") api_pattern = re.compile(r'var apiUrl = "([^"]+)"') # 捕获双引号内的URL api_url = re.search(api_pattern, response.text).group(1) # 提取第一个匹配的API print(f"提取到的API地址:{api_url}") # 3. 用API地址直接请求数据(比解析HTML更高效) api_response = requests.get(api_url, headers={"User-Agent": "Mozilla/5.0 ..."}) print(f"API返回数据:{api_response.json()}")
三、动态页面处理:Selenium(自动化浏览器,突破 JS 渲染)
-
核心定位:自动化测试工具,可模拟真实浏览器(Chrome、Firefox)的行为(如打开页面、点击按钮、输入文本、滚动页面),解决 “requests 无法执行 JavaScript” 的问题(如 SPA 单页应用、动态加载数据的页面)。
-
核心作用:处理 “动态渲染页面”(如 Vue/React 项目、需要登录后加载的数据、点击 “加载更多” 才能获取的列表),本质是 “用代码控制浏览器”,获取浏览器渲染后的完整 HTML。
-
关键知识点:
- 环境依赖:需下载对应浏览器的驱动(如 Chrome 对应 chromedriver,版本需与浏览器一致),或用
webdriver-manager
自动管理驱动。 - 核心操作:
- 启动浏览器:
webdriver.Chrome()
(默认打开可视化浏览器),options.add_argument("--headless=new")
(无头模式,无界面,适合服务器运行)。 - 页面操作:
driver.get(url)
(打开 URL)、driver.find_element(By.XPATH, xpath)
(定位元素)、element.click()
(点击)、element.send_keys(text)
(输入文本)。 - 数据提取:
driver.page_source
(获取渲染后的完整 HTML,可交给 BS4 或 lxml 解析)。
- 启动浏览器:
- 环境依赖:需下载对应浏览器的驱动(如 Chrome 对应 chromedriver,版本需与浏览器一致),或用
-
实战应用(爬取动态加载的商品列表):
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options from bs4 import BeautifulSoup import time # 1. 配置Chrome选项(无头模式,提升速度) chrome_options = Options() chrome_options.add_argument("--headless=new") # 无头模式 chrome_options.add_argument("--user-agent=Mozilla/5.0 ...") # 模拟浏览器UA # 2. 启动浏览器 driver = webdriver.Chrome(options=chrome_options) try: # 3. 打开目标页面 driver.get("https://example-mall.com/goods/laptop") # 4. 模拟滚动页面(触发动态加载,加载更多商品) for _ in range(3): # 滚动3次,每次等待2秒 driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 滚动到底部 time.sleep(2) # 等待数据加载 # 5. 获取渲染后的完整HTML,用BS4解析 soup = BeautifulSoup(driver.page_source, "lxml") product_list = soup.find_all("li", class_="product-item") # 6. 提取数据 for product in product_list: name = product.find("h3", class_="product-name").text.strip() price = product.find("span", class_="current-price").text.strip() print(f"名称:{name} | 价格:{price}") finally: driver.quit() # 关闭浏览器,释放资源
四、数据存储库(爬取后 “存好宝藏”)
提取数据后需持久化存储(避免内存丢失),核心库为 pandas(Excel/CSV)、sqlite3(轻量数据库)、MongoDB(NoSQL 数据库)。
1. pandas(数据处理 + Excel/CSV 存储,轻量首选)
-
核心定位:数据处理库,但自带便捷的文件存储功能,支持将列表 / 字典数据快速写入 Excel(
.xlsx
)或 CSV(.csv
),适合小规模数据(万级以内)的存储与后续分析。 -
核心作用:解决 “手动拼接 Excel/CSV 繁琐” 的问题,尤其适合需要后续用 Excel 分析的数据(如电商商品价格对比、新闻关键词统计)。
-
实战应用(将商品数据存入 Excel):
import pandas as pd import requests from bs4 import BeautifulSoup # 1. 爬取商品数据(省略请求和解析步骤,直接构造数据列表) goods_data = [] url = "https://example-mall.com/goods/laptop" response = requests.get(url, headers={"User-Agent": "Mozilla/5.0 ..."}) soup = BeautifulSoup(response.text, "lxml") for product in soup.find_all("li", class_="product-item"): goods_data.append({ "商品名称": product.find("h3", class_="product-name").text.strip(), "价格": product.find("span", class_="current-price").text.strip(), "链接": product.find("a")["href"] }) # 2. 用pandas存入Excel df = pd.DataFrame(goods_data) # 将列表转为DataFrame df.to_excel("电商商品列表.xlsx", index=False, engine="openpyxl") # 写入Excel,不保留索引 print("数据已存入:电商商品列表.xlsx")
2. MongoDB(NoSQL 数据库,大规模 / 非结构化数据首选)
-
核心定位:文档型 NoSQL 数据库,存储格式为 JSON-like(BSON),无需预先定义表结构,适合存储大规模、结构不固定的数据(如爬取的新闻正文、商品评论、多字段嵌套数据)。
-
核心作用:解决 “Excel/CSV 无法存储大规模数据” 和 “数据结构多变” 的问题(如部分商品有 “折扣价”,部分没有,MongoDB 可灵活存储)。
-
实战应用(将商品数据存入 MongoDB):
from pymongo import MongoClient import requests from bs4 import BeautifulSoup # 1. 连接MongoDB(默认本地连接,端口27017) client = MongoClient("mongodb://localhost:27017/") # 2. 创建/选择数据库(名为spider_db) db = client["spider_db"] # 3. 创建/选择集合(类似表,名为goods_collection) collection = db["goods_collection"] # 4. 爬取商品数据 goods_data = [] url = "https://example-mall.com/goods/laptop" response = requests.get(url, headers={"User-Agent": "Mozilla/5.0 ..."}) soup = BeautifulSoup(response.text, "lxml") for product in soup.find_all("li", class_="product-item"): goods_data.append({ "商品名称": product.find("h3", class_="product-name").text.strip(), "价格": product.find("span", class_="current-price").text.strip(), "链接": product.find("a")["href"], "爬取时间": pd.Timestamp.now() # 新增爬取时间字段 }) # 5. 插入数据(insert_many插入多条,insert_one插入单条) if goods_data: collection.insert_many(goods_data) print(f"成功插入 {len(goods_data)} 条数据到MongoDB")
五、实战选型策略(避坑指南)
- 请求库选型:
- 小规模爬取(<100 页):用
requests
(简单、无需异步)。 - 大规模爬取(>100 页):用
aiohttp
(异步提升效率),配合Semaphore
控制并发。 - 动态页面:先用
Chrome开发者工具(F12)
分析是否有 API 接口(Network→XHR),有则用requests/aiohttp
直接请求 API(效率高),无则用Selenium
(万不得已才用,性能消耗大)。
- 小规模爬取(<100 页):用
- 解析库选型:
- HTML 结构规整:优先用
lxml+xpath
(速度快、定位精准)。 - HTML 结构混乱 / 入门学习:用
Beautiful Soup
(语法友好)。 - 非标签文本(如 JS 代码、日志):用
re
(正则匹配)。 - 绝对避免:用
re
解析完整 HTML(HTML 结构灵活,正则易出错,维护成本高)。
- HTML 结构规整:优先用
- 存储库选型:
- 数据量小(<1 万条)+ 需 Excel 分析:用
pandas
存 Excel/CSV。 - 数据量大(>1 万条)+ 结构多变:用
MongoDB
。 - 需 SQL 查询(如按价格筛选商品):用
sqlite3
(轻量)或MySQL
(大规模)。
- 数据量小(<1 万条)+ 需 Excel 分析:用
六、总结
Python 爬虫的核心是 “工具链组合”,不同库对应不同环节:
- 发起请求:
requests
(同步)、aiohttp
(异步)。 - 解析数据:
Beautiful Soup
(HTML 入门)、lxml
(HTML 高性能 + xpath)、re
(复杂文本)。 - 动态处理:
Selenium
(浏览器自动化)。 - 存储数据:
pandas
(Excel/CSV)、MongoDB
(大规模 NoSQL)。
实战中需先分析目标页面(静态 / 动态、是否有 API),再选择最优工具组合,避免 “一把锤子敲所有钉子”(如明明有 API 却用 Selenium 爬取,浪费资源)。
更多推荐
所有评论(0)