Python 爬虫练习 批量爬取导师信息与照片
'# Python 爬虫练习 批量爬取导师信息与照片
一、背景与问题
在科研合作、学术交流等场景中,获取导师的详细信息(如研究方向、联系方式、学术成果)和高质量照片是常见需求。然而,传统人工整理方式效率低下,而爬虫技术能有效解决这一问题。
但实际开发中会遇到诸多挑战:
- 目标网站存在反爬虫机制(如验证码、请求头限制)
- 导师信息分散在多个页面中需要分页处理
- 照片可能通过JavaScript动态加载
- 需要处理异构数据格式(如JSON嵌套结构)
- 需要遵守网站的robots.txt规则
二、基本原理
爬虫系统的核心是模拟浏览器行为,完成以下三个步骤:
- 网络请求:使用HTTP协议向目标服务器发送请求,获取原始数据(HTML/JSON)
- 数据解析:分析响应内容,提取所需信息(HTML解析、JSON提取)
- 数据存储:将提取数据持久化保存(数据库、文件系统、云存储)
对于动态加载内容的网页,还需要引入浏览器自动化工具(如Selenium)模拟真实用户操作。
三、环境准备
pip install requests beautifulsoup4 lxml selenium需要额外安装浏览器驱动(如ChromeDriver)并配置环境变量。
四、核心实现
1. 基础请求与响应处理
import requests
from bs4 import BeautifulSoup
def fetch_page(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4443.116 Safari/537.36'
}
response = requests.get(url, headers=headers, timeout=10)
response.encoding = 'utf-8'
return response.text关键点解释:
- 设置合理的User-Agent避免被识别为爬虫
- 设置超时时间防止程序卡死
- 处理响应编码(有些网站返回的是gbk编码)
2. 动态内容处理(使用Selenium)
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def get_dynamic_content(url):
chrome_options = Options()
chrome_options.add_argument('--headless') # 无头模式
chrome_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(options=chrome_options)
try:
driver.get(url)
# 等待JavaScript加载
driver.implicitly_wait(10)
return driver.page_source
finally:
driver.quit()注意事项:
- 需要安装Chrome浏览器和对应版本的chromedriver
- 无头模式可能被反爬虫机制检测到
- 考虑使用代理IP池避免IP封禁
3. 数据提取与存储
import sqlite3
def save_to_sqlite(data):
conn = sqlite3.connect('teachers.db')
c = conn.cursor()
# 创建表(如果不存在)
c.execute('''CREATE TABLE IF NOT EXISTS teachers
(id INTEGER PRIMARY KEY, name TEXT, title TEXT, photo_url TEXT, research_area TEXT)''')
# 插入数据
c.executemany('INSERT OR IGNORE INTO teachers VALUES (?,?,?,?,$)',
[(d['id'], d['name'], d['title'], d['photo_url'], d['research_area']) for d in data])
conn.commit()
conn.close()优化点:
- 使用
INSERT OR IGNORE避免重复插入 - 使用事务保证数据一致性
- 可扩展为MySQL/PostgreSQL等数据库
五、完整案例:某高校导师信息爬取
项目结构
teacher_crawler/
├── main.py
├── utils/
│ ├── request_utils.py
│ └── parser_utils.py
└── db/
└── teachers.db主程序实现
# main.py
import requests
from bs4 import BeautifulSoup
import sqlite3
def main():
base_url = 'https://example-university.edu/teachers'
pages = 3 # 爬取前3页
for page in range(1, pages+1):
url = f"{base_url}?page={page}"
html = fetch_page(url)
soup = BeautifulSoup(html, 'html.parser')
for item in soup.select('.teacher-item'):
name = item.select_one('.name').text.strip()
title = item.select_one('.title').text.strip()
photo_url = item.select_one('img')['src']
research_area = item.select_one('.research-area').text.strip()
# 保存到数据库
save_to_sqlite({
'id': page*10 + i, # 假设每页10条数据
'name': name,
'title': title,
'photo_url': photo_url,
'research_area': research_area
})动态内容处理扩展
# utils/request_utils.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def get_dynamic_content(url):
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(options=chrome_options)
try:
driver.get(url)
driver.implicitly_wait(10)
return driver.page_source
finally:
driver.quit()六、源码解析
1. 请求头构造
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4443.116 Safari/537.36'
}- 模拟现代浏览器的特征
- 可添加其他字段如
Accept-Language、Referer
2. 数据解析
soup.select('.teacher-item')- 使用CSS选择器提高解析效率
select_one用于获取单个元素- 需要处理可能的空值(
text.strip())
3. 数据存储优化
c.executemany('INSERT OR IGNORE INTO teachers VALUES (?,?,?,?,$)',
[(d['id'], d['name'], d['title'], d['photo_url'], d['research_area']) for d in data])- 批量插入提升性能
- 使用
OR IGNORE避免重复数据 - 可考虑使用
UPSERT语句(需数据库支持)
七、进阶使用
1. 并发处理优化
import concurrent.futures
def crawl_page(page):
url = f"{base_url}?page={page}"
html = fetch_page(url)
# 解析并保存数据...
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
executor.map(crawl_page, range(1, pages+1))2. 代理IP池配置
def fetch_page(url):
proxies = {
'http': 'http://10.10.1.10:3128',
'https': 'http://10.10.1.10:1080'
}
response = requests.get(url, headers=headers, timeout=10, proxies=proxies)3. 动态内容处理优化
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def get_dynamic_content(url):
driver.get(url)
# 等待特定元素加载
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, 'teacher-item'))
)
return driver.page_source八、性能与工程实践
1. 性能优化策略
| 优化点 | 方法 | 效果 |
|---|---|---|
| 线程数 | 使用ThreadPoolExecutor | 提升并发效率 |
| 请求头 | 随机User-Agent | 避免被识别为爬虫 |
| 重试机制 | requests重试库 | 提高稳定性 |
| 限速 | time.sleep() | 避免触发反爬虫 |
2. 异常处理方案
try:
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
# 可添加重试逻辑3. 安全风险分析
- 法律风险:需遵守《计算机软件保护条例》和网站robots.txt规则
反爬虫机制:常见手段包括:
- 验证码识别(需引入第三方服务)
- 请求频率限制(需使用时间间隔)
- IP封禁(需使用代理池)
九、常见问题与踩坑
1. 验证码处理
错误示例:
# 直接请求包含验证码的页面
response = requests.get('https://example.com/teachers?captcha=1')解决方案:
- 使用第三方验证码识别服务(如云打码)
- 使用Selenium模拟人工输入
2. 动态内容加载问题
错误示例:
# 仅获取静态HTML
html = fetch_page('https://example.com/dynamic-page')解决方案:
- 使用Selenium等待元素加载
- 检查开发者工具中的Network面板确认数据源
3. 数据清洗问题
错误示例:
# 直接使用text属性获取数据
research_area = item.select_one('.research-area').text改进方案:
# 处理多行文本
research_area = '\n'.join([line.strip() for line in item.select_one('.research-area').text.split('\n')])十、最佳实践
1. 推荐技术栈组合
| 技术 | 说明 |
|---|---|
| requests | 简单高效的HTTP请求 |
| BeautifulSoup | 快速解析静态HTML |
| Selenium | 处理动态内容 |
| SQLite | 轻量级数据存储 |
| Proxy池 | 避免IP封禁 |
2. 推荐开发流程
- 分析网站结构,确认数据源
- 编写基础爬虫验证可行性
- 引入反爬虫机制处理
- 实现数据清洗和存储
- 添加异常处理和日志记录
- 部署到服务器并监控运行
3. 推荐的目录结构
teacher_crawler/
├── main.py
├── utils/
│ ├── request_utils.py
│ └── parser_utils.py
├── db/
│ └── teachers.db
├── logs/
│ └── crawler.log
└── config/
└── settings.py十一、总结
批量爬取导师信息与照片是典型的数据采集场景,涉及多技术栈的综合应用。本文深入解析了爬虫的实现原理,提供了完整的代码示例和优化方案,涵盖静态页面解析、动态内容处理、数据存储等关键环节。
在实际开发中,建议:
- 对于简单页面使用requests+BeautifulSoup
- 对于动态内容使用Selenium
- 对于大规模数据采用分布式爬虫框架
- 始终遵守网站的robots.txt规则
同时需要警惕法律风险和反爬虫机制,建议在合法合规的前提下进行数据采集。通过合理的技术选型和工程实践,可以有效提升爬虫系统的稳定性和扩展性。
评论已关闭