Python爬虫是获取互联网数据的重要技术,广泛应用于数据采集、数据分析、自动化测试等领域。本文将详细介绍Python爬虫的常用库、使用方法、实战案例以及常见问题解答,帮助你从入门到精通Python爬虫技术。
一、爬虫基础概念
1. 什么是网络爬虫?
答:网络爬虫(Web Crawler)是一种自动化程序,它可以模拟浏览器访问网页,获取网页内容,并从中提取有用的数据。爬虫广泛应用于搜索引擎、数据采集、内容聚合等领域。
2. 爬虫的工作原理
- 发送请求:向目标网站发送HTTP请求
- 获取响应:接收服务器返回的HTML页面
- 解析页面:从HTML中提取目标数据
- 存储数据:将数据保存到数据库或文件
- 递归爬取:发现新的链接并继续爬取
3. 爬虫的分类
- 通用爬虫:如搜索引擎爬虫,爬取整个互联网
- 聚焦爬虫:只爬取特定领域的网页
- 增量爬虫:只爬取更新的内容
- 分布式爬虫:多台机器协同爬取
二、常用爬虫库介绍
1. requests库
requests是Python最常用的HTTP请求库,简单易用,功能强大。
安装
pip install requests
基本用法
import requests
# GET请求
response = requests.get('https://www.example.com')
print(response.status_code)
print(response.text)
# POST请求
data = {'username': 'test', 'password': '123456'}
response = requests.post('https://www.example.com/login', data=data)
# 设置请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0'
}
response = requests.get('https://www.example.com', headers=headers)
# 设置超时
response = requests.get('https://www.example.com', timeout=10)
# 会话保持
session = requests.Session()
session.get('https://www.example.com/login')
response = session.get('https://www.example.com/profile')
常见方法
| 方法 | 说明 |
|---|---|
| requests.get() | 发送GET请求 |
| requests.post() | 发送POST请求 |
| requests.put() | 发送PUT请求 |
| requests.delete() | 发送DELETE请求 |
| response.text | 获取响应文本 |
| response.json() | 获取JSON响应 |
| response.content | 获取二进制响应 |
| response.headers | 获取响应头 |
2. BeautifulSoup库
BeautifulSoup是一个HTML/XML解析库,可以方便地从网页中提取数据。
安装
pip install beautifulsoup4
基本用法
from bs4 import BeautifulSoup
html = '''
<html>
<head><title>测试页面</title></head>
<body>
<div class="content">
<h1>Hello World</h1>
<p class="desc">这是一段描述</p>
<a href="https://example.com">链接</a>
</div>
</body>
</html>
'''
soup = BeautifulSoup(html, 'html.parser')
# 通过标签名查找
title = soup.title
print(title.string)
# 通过类名查找
content = soup.find('div', class_='content')
print(content)
# 通过id查找
element = soup.find(id='main')
# 查找多个元素
paragraphs = soup.find_all('p')
# 获取文本
text = content.get_text()
# 获取属性
link = soup.find('a')
print(link['href'])
选择器方法
| 方法 | 说明 |
|---|---|
| find() | 查找第一个匹配的元素 |
| find_all() | 查找所有匹配的元素 |
| select() | 使用CSS选择器查找 |
| select_one() | 使用CSS选择器查找第一个 |
| get_text() | 获取元素文本 |
| ['attr'] | 获取元素属性 |
3. lxml库
lxml是一个高性能的HTML/XML解析库,支持XPath选择器。
安装
pip install lxml
基本用法
from lxml import etree
html = '''
<html>
<body>
<div id="container">
<ul>
<li class="item">Item 1</li>
<li class="item">Item 2</li>
<li class="item">Item 3</li>
</ul>
</div>
</body>
</html>
'''
tree = etree.HTML(html)
# XPath选择器
items = tree.xpath('//li[@class="item"]/text()')
print(items)
# 获取属性
links = tree.xpath('//a/@href')
# 层级选择
container = tree.xpath('//div[@id="container"]')[0]
items = container.xpath('.//li/text()')
4. Scrapy框架
Scrapy是一个强大的爬虫框架,提供了完整的爬虫解决方案。
安装
pip install scrapy
创建爬虫项目
# 创建项目
scrapy startproject myspider
# 创建爬虫
cd myspider
scrapy genspider example example.com
爬虫代码示例
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example.com']
start_urls = ['http://example.com']
def parse(self, response):
# 提取数据
title = response.css('h1::text').get()
yield {'title': title}
# 提取链接
links = response.css('a::attr(href)').getall()
for link in links:
yield response.follow(link, callback=self.parse)
运行爬虫
scrapy crawl example
scrapy crawl example -o output.json
5. Selenium库
Selenium是一个自动化测试工具,可以模拟浏览器行为,适用于动态网页。
安装
pip install selenium
基本用法
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
# 启动浏览器
driver = webdriver.Chrome()
# 访问网页
driver.get('https://www.google.com')
# 查找元素
search_box = driver.find_element(By.NAME, 'q')
# 输入内容
search_box.send_keys('Python爬虫')
# 提交搜索
search_box.send_keys(Keys.ENTER)
# 等待加载
time.sleep(2)
# 提取数据
results = driver.find_elements(By.CSS_SELECTOR, 'h3')
for result in results:
print(result.text)
# 关闭浏览器
driver.quit()
6. 其他常用库
| 库名 | 用途 |
|---|---|
| urllib | Python标准库,HTTP请求 |
| re | 正则表达式,文本匹配 |
| json | JSON数据处理 |
| pandas | 数据处理和分析 |
| pymysql | MySQL数据库操作 |
| redis | Redis缓存操作 |
| fake-useragent | 随机生成User-Agent |
| pyquery | 类似jQuery的选择器 |
三、爬虫实战案例
案例1:爬取新闻网站
import requests
from bs4 import BeautifulSoup
def crawl_news(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0'
}
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
news_list = []
articles = soup.find_all('article', class_='news-item')
for article in articles:
title = article.find('h2').get_text()
link = article.find('a')['href']
summary = article.find('p').get_text()
news_list.append({
'title': title,
'link': link,
'summary': summary
})
return news_list
if __name__ == '__main__':
news = crawl_news('https://news.example.com')
for item in news:
print(f"标题: {item['title']}")
print(f"链接: {item['link']}")
print(f"摘要: {item['summary']}")
print('---')
案例2:爬取图片
import requests
from bs4 import BeautifulSoup
import os
def download_images(url, save_dir='images'):
if not os.path.exists(save_dir):
os.makedirs(save_dir)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0'
}
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
images = soup.find_all('img', class_='gallery-img')
for i, img in enumerate(images):
img_url = img['src']
if not img_url.startswith('http'):
img_url = 'https://example.com' + img_url
try:
img_response = requests.get(img_url, headers=headers)
with open(f'{save_dir}/image_{i+1}.jpg', 'wb') as f:
f.write(img_response.content)
print(f'下载成功: image_{i+1}.jpg')
except Exception as e:
print(f'下载失败: {img_url}, 错误: {e}')
if __name__ == '__main__':
download_images('https://example.com/gallery')
案例3:爬取API数据
import requests
import json
def crawl_api(base_url, pages=5):
all_data = []
for page in range(1, pages+1):
url = f'{base_url}?page={page}&limit=20'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0',
'Authorization': 'Bearer your_token'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
data = response.json()
all_data.extend(data['items'])
print(f'第 {page} 页爬取完成')
else:
print(f'第 {page} 页爬取失败')
return all_data
if __name__ == '__main__':
data = crawl_api('https://api.example.com/data')
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f'共爬取 {len(data)} 条数据')
四、反爬虫策略与应对
1. 常见反爬虫手段
- User-Agent检测:检查请求头中的User-Agent
- IP封禁:封禁频繁访问的IP地址
- Cookie验证:需要登录或携带特定Cookie
- 验证码:图形验证码、滑块验证等
- 频率限制:限制单位时间内的请求次数
- 动态渲染:使用JavaScript动态生成内容
- Referer检查:检查请求来源
2. 反爬虫应对策略
策略1:设置请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0',
'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',
'Referer': 'https://www.example.com',
'Connection': 'keep-alive'
}
策略2:使用代理IP
proxies = {
'http': 'http://proxy.example.com:8888',
'https': 'https://proxy.example.com:8888'
}
response = requests.get('https://www.example.com', proxies=proxies)
策略3:设置请求间隔
import time
import random
for url in urls:
response = requests.get(url, headers=headers)
time.sleep(random.uniform(1, 3)) # 随机等待1-3秒
策略4:使用Cookie池
import random
cookies_pool = [
{'session': 'cookie1'},
{'session': 'cookie2'},
{'session': 'cookie3'}
]
cookie = random.choice(cookies_pool)
response = requests.get('https://www.example.com', cookies=cookie)
策略5:使用Selenium
Selenium可以模拟真实浏览器行为,绕过大部分反爬虫机制。
3. 验证码处理
- 手动输入:适合小规模爬取
- 打码平台:使用第三方验证码识别服务
- 机器学习识别:训练模型识别简单验证码
- 滑动验证:使用Selenium模拟滑动
五、爬虫常见问题解答
1. 爬虫被封禁了怎么办?
答:可以尝试以下方法:
- 更换IP地址或使用代理
- 清空Cookie,重新请求
- 降低请求频率
- 更换User-Agent
- 等待一段时间后再试
2. 如何处理动态加载的内容?
答:有以下几种方法:
- 分析API:使用浏览器开发者工具查找数据接口
- Selenium:使用浏览器自动化工具
- Pyppeteer:Python版的Puppeteer
- Splash:渲染JavaScript的服务
3. 如何处理大量数据的存储?
答:可以使用以下方式存储数据:
- CSV/JSON文件:适合中小规模数据
- MySQL/PostgreSQL:适合大规模结构化数据
- MongoDB:适合非结构化数据
- Redis:适合缓存和临时存储
- Elasticsearch:适合全文搜索
4. 如何实现分布式爬虫?
答:可以使用以下方案:
- Scrapy-Redis:基于Redis的分布式爬虫
- Celery:分布式任务队列
- 消息队列:如RabbitMQ、Kafka
- 分布式存储:如Hadoop、Spark
5. 爬虫的合法性问题
答:爬取数据需要遵守法律法规:
- 查看目标网站的robots.txt文件
- 遵守网站的服务条款
- 不要爬取敏感信息(个人信息、商业机密等)
- 不要对网站造成过大压力
- 数据使用要遵守版权法
6. 如何提高爬虫效率?
答:可以从以下方面优化:
- 并发请求:使用多线程、多进程或异步IO
- 连接池:复用TCP连接
- 缓存策略:避免重复请求
- 增量爬取:只爬取更新的内容
- 分布式爬取:多台机器协同工作
六、高级爬虫技术
1. 异步爬虫
import asyncio
import aiohttp
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main(urls):
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
results = await asyncio.gather(*tasks)
return results
if __name__ == '__main__':
urls = ['https://example.com/page1', 'https://example.com/page2']
results = asyncio.run(main(urls))
2. Scrapy分布式爬虫
# settings.py
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
SCHEDULER = 'scrapy_redis.scheduler.Scheduler'
SCHEDULER_PERSIST = True
3. 爬虫框架对比
| 框架 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| requests+BS4 | 简单易用 | 功能有限 | 小型爬虫 |
| Scrapy | 功能强大 | 学习曲线陡 | 大型爬虫 |
| Selenium | 支持动态渲染 | 速度慢 | 复杂页面 |
| PySpider | 可视化界面 | 维护不活跃 | 中小型爬虫 |
总结
Python爬虫是一项非常实用的技能,掌握好爬虫技术可以帮助你获取各种互联网数据。本文介绍了:
- 基础概念:爬虫的工作原理和分类
- 常用库:requests、BeautifulSoup、lxml、Scrapy、Selenium
- 实战案例:新闻爬取、图片下载、API爬取
- 反爬虫策略:应对各种反爬虫手段
- 常见问题:解答常见的爬虫问题
- 高级技术:异步爬虫、分布式爬虫
在实际使用中,要注意遵守法律法规,尊重网站的robots.txt,合理控制爬取频率,避免对目标网站造成影响。