一、爬取原理概述
网页内容爬取的核心原理是模拟浏览器的网络请求行为,从目标服务器获取数据并进行结构化处理。一个完整的爬虫工作流程通常包含以下五个核心步骤:
- 发送HTTP请求:爬虫程序通过HTTP协议向目标URL发送GET或POST请求,携带必要的请求头(如User-Agent、Cookie等)以模拟真实用户访问。
- 获取HTML响应:目标服务器处理请求后,返回包含网页内容的HTML文档、JSON数据或其他格式的响应体。
- 解析HTML文档:使用解析器将非结构化的HTML文本转换为可遍历的文档树结构,便于程序定位和提取信息。
- 提取目标数据:通过CSS选择器、XPath或正则表达式等方式,从文档树中精准提取所需的文本、链接、图片等数据。
- 存储数据:将提取到的结构化数据持久化保存到本地文件(如JSON、CSV)或数据库中,供后续分析和使用。
整个流程可以概括为:请求 -> 响应 -> 解析 -> 提取 -> 存储。在实际开发中,还需要考虑异常处理、重试机制、反爬应对以及数据清洗等环节,以确保爬虫的稳定性和数据的准确性。
二、环境准备
在开始编写爬虫之前,需要确保本地已安装Python 3环境,并安装以下核心依赖库:
- requests:用于发送HTTP请求,是Python中最流行的HTTP库,API简洁易用。
- beautifulsoup4:用于解析HTML和XML文档,提供直观的导航和搜索接口。
- lxml:高性能的HTML/XML解析器,作为BeautifulSoup的解析后端,速度远快于默认的html.parser。
使用以下pip命令一键安装:
pip install requests beautifulsoup4 lxml
如果后续需要处理动态渲染页面,还需安装浏览器自动化工具:
pip install selenium playwright
playwright install
三、基础爬取示例
以下是一个完整的基础爬虫示例,演示了如何爬取一个网页的标题、正文文本和所有链接。代码包含了请求头设置、HTML解析、数据提取和异常处理。
import requests
from bs4 import BeautifulSoup
def fetch_page_content(url):
"""
爬取指定URL的网页内容,提取标题、正文和链接。
"""
# 设置请求头,模拟浏览器访问,避免被基础反爬拦截
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/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8"
}
try:
# 发送GET请求,设置超时时间为10秒
response = requests.get(url, headers=headers, timeout=10)
# 检查HTTP状态码,非200则抛出异常
response.raise_for_status()
# 设置响应编码,避免中文乱码
response.encoding = response.apparent_encoding
# 使用lxml解析器创建BeautifulSoup对象
soup = BeautifulSoup(response.text, "lxml")
# 提取网页标题
title = soup.title.string.strip() if soup.title else "无标题"
# 提取正文文本(以body标签为例,去除多余空白)
body_tag = soup.find("body")
content_text = body_tag.get_text(strip=True, separator="\n") if body_tag else ""
# 提取页面中所有链接
links = []
for a_tag in soup.find_all("a", href=True):
links.append({
"text": a_tag.get_text(strip=True),
"href": a_tag["href"]
})
return {
"title": title,
"content": content_text[:500], # 仅返回前500字符作为预览
"links_count": len(links),
"links": links[:10] # 仅返回前10条链接作为示例
}
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
return None
except Exception as e:
print(f"解析失败: {e}")
return None
if __name__ == "__main__":
target_url = "https://example.com"
result = fetch_page_content(target_url)
if result:
print(f"标题: {result['title']}")
print(f"正文预览: {result['content']}")
print(f"链接数量: {result['links_count']}")
for link in result["links"]:
print(f" - {link['text']}: {link['href']}")
四、进阶爬取技巧
4.1 处理动态渲染页面(JavaScript渲染)
当目标网站使用React、Vue等前端框架构建SPA应用,或存在懒加载、滚动加载等动态内容时,直接请求HTML无法获取完整数据。此时需要使用浏览器自动化工具来执行JavaScript并获取渲染后的DOM。
Selenium方案:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def fetch_dynamic_page_selenium(url):
options = Options()
options.add_argument("--headless") # 无头模式,不显示浏览器窗口
options.add_argument("--disable-gpu")
driver = webdriver.Chrome(options=options)
try:
driver.get(url)
driver.implicitly_wait(10) # 隐式等待10秒
page_source = driver.page_source
return page_source
finally:
driver.quit()
Playwright方案(推荐):
Playwright是更现代的浏览器自动化框架,支持异步、自动等待、多浏览器,性能优于Selenium。
from playwright.sync_api import sync_playwright
def fetch_dynamic_page_playwright(url):
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto(url, wait_until="networkidle") # 等待网络空闲
content = page.content()
browser.close()
return content
使用场景判断:如果API接口可以直接获取JSON数据(通过浏览器开发者工具Network面板查看),优先使用requests直接请求API,效率远高于浏览器自动化。仅在无法绕过JS渲染时才使用Selenium或Playwright。
4.2 处理登录和Cookie
方式一:使用requests.Session保持会话
Session会自动管理Cookie,适合需要登录后连续访问多个页面的场景。
session = requests.Session()
# 第一次请求登录接口,Cookie自动保存到session中
session.post("https://example.com/login", data={
"username": "user",
"password": "pass"
})
# 后续请求自动携带Cookie
response = session.get("https://example.com/dashboard")
方式二:手动设置Cookie
从浏览器开发者工具中复制Cookie字符串,直接附加到请求头中。
cookies = {
"session_id": "abc123",
"token": "xyz789"
}
response = requests.get("https://example.com/api/data", cookies=cookies)
方式三:模拟表单提交
分析登录表单的action地址和字段名,使用POST请求提交。
login_data = {
"username": "your_username",
"password": "your_password",
"csrf_token": "从页面中提取的csrf令牌"
}
response = session.post("https://example.com/api/login", data=login_data)
4.3 反爬机制应对
- User-Agent检测:维护一个UA池,每次请求随机选取,避免固定UA被识别为爬虫。
- IP频率限制:使用代理IP池轮换出口IP,并在请求之间添加随机延时(time.sleep(random.uniform(1, 3))),模拟人类浏览节奏。
- 验证码:接入打码平台API自动识别,或使用OCR库(如ddddocr)本地识别简单验证码。复杂滑块验证需分析轨迹算法。
- JS加密参数:通过浏览器开发者工具断点调试,逆向分析JS代码中的加密逻辑,在Python中复现或使用Node.js执行。
- 签名验证:分析请求中的sign/token参数生成规则,通常在JS中以时间戳、nonce、密钥等拼接后做MD5/HMAC运算,需完整还原算法。
4.4 数据提取方法对比
| 方法 | 优点 | 缺点 | 适用场景 |
| CSS选择器 | 语法简洁,与前端开发一致 | 复杂层级表达力有限 | 常规HTML解析 |
| XPath | 表达力强,支持轴定位和函数 | 语法较复杂 | 复杂DOM结构定位 |
| 正则表达式 | 不依赖DOM结构,速度快 | 易出错,维护成本高 | 提取固定格式文本 |
CSS选择器示例:
titles = soup.select("div.article h2.title")
XPath示例(需配合lxml):
from lxml import etree
tree = etree.HTML(html_text)
titles = tree.xpath("//div[@class='article']//h2[@class='title']/text()")
正则表达式示例:
import re
emails = re.findall(r"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+", html_text)
五、数据持久化
保存为JSON文件:
import json
data = [{"title": "文章1", "url": "https://..."}]
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
保存为CSV文件:
import csv
data = [{"title": "文章1", "url": "https://..."}]
with open("data.csv", "w", encoding="utf-8-sig", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["title", "url"])
writer.writeheader()
writer.writerows(data)
存入SQLite数据库:
import sqlite3
conn = sqlite3.connect("data.db")
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS articles (title TEXT, url TEXT)")
cursor.executemany("INSERT INTO articles VALUES (?, ?)",
[("文章1", "https://..."), ("文章2", "https://...")])
conn.commit()
conn.close()
六、爬虫伦理与法律合规
编写和运行爬虫时,必须严格遵守以下准则:
- 遵守robots.txt协议:在爬取前检查目标网站的/robots.txt文件,尊重网站声明的爬取规则。
- 控制请求频率:设置合理的请求间隔,避免对目标服务器造成过大压力,必要时主动降低并发。
- 尊重版权和隐私:不爬取受版权保护的完整内容用于商业分发,不采集个人隐私数据。
- 不爬取受法律保护的数据:涉及国家安全、公民个人信息、商业秘密等数据,严禁爬取。
- 了解当地法律法规:熟悉《网络安全法》《数据安全法》《个人信息保护法》等相关法律,确保爬虫行为合法合规。
七、常用工具推荐
- Scrapy:Python异步爬虫框架,内置中间件、管道、调度器,适合大规模分布式爬取。
- Playwright:微软开源的现代浏览器自动化库,支持Chromium/Firefox/WebKit,API设计优秀。
- curl/wget:命令行HTTP工具,适合快速测试接口、下载文件。
- Postman:API调试工具,可快速验证接口参数、查看响应结构,辅助爬虫开发。
- httpx:支持HTTP/2和异步的requests替代品,适合高并发场景。
八、实战练习建议
- 爬取知乎热榜标题和链接:练习基础请求、HTML解析和数据提取,注意处理知乎的反爬策略。
- 爬取天气预报数据并保存为CSV:练习多字段提取、数据清洗和CSV存储,可尝试多个城市批量爬取。
- 爬取某电商网站商品列表:练习分页处理、动态加载应对和商品详情翻页爬取。
- 使用代理爬取需要登录的网站:综合运用Session、代理IP、UA轮换和请求延时,构建一个健壮的登录态爬虫。
通过以上练习,学习者可以逐步掌握从基础到进阶的爬虫技能,并在实践中培养对反爬机制的敏感度和合规意识。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/2503_91800161/article/details/167177889




