本文将介绍一个使用Python和DrissionPage库实现的网页爬虫,该爬虫用于从"www.nyato.com"网站抓取展览信息并保存到CSV文件中。
爬虫概述
这个爬虫的主要功能是:
-
遍历网站的多个分页(共1312页)
-
从每个分页中提取展览列表
-
进入每个展览的详情页获取详细信息
-
将所有信息整理并保存到CSV文件中
技术栈
-
DrissionPage: 一个强大的网页自动化工具,结合了浏览器自动化和网络请求功能
-
fake_useragent: 用于生成随机User-Agent,模拟不同浏览器访问
-
re: 正则表达式模块,用于从URL中提取评分信息
-
random: 生成随机延迟,避免被网站封禁
代码结构分析
1. 保存功能
def save(long_str):
try:
with open(f"exhibition.csv", "a+", encoding="utf-8") as f:
f.write(long_str)
except Exception as e:
print(e)
这个函数负责将抓取到的数据追加写入到"exhibition.csv"文件中。使用a+
模式确保文件不存在时会创建,存在时则追加内容。
2. 详情页抓取
def get_detail(page, url):
try:
page.get(url)
# 详细地址
address_detail = page.ele("xpath://span[@class='fl mr10']").text
# 时间间隔
time_interval = page.ele("xpath://div[@class='h25 line25 s6 f14 w100s mb10']").texts()[3].strip()
# 票价
ticket_price = page.ele("xpath://b[@class='f40']").text
# 匹配得分
score_url = page.ele("xpath://div[@class='mt10']/img").attr('src')
score = re.search(r"//static.nyato.cn/expo-image/stars/star-(\d\.\d).png", score_url).group(1)
# 其它信息
other = ",".join(page.eles("xpath://span[@class='sf6 f18 fwb ml15']").texts())
return ticket_price, time_interval, address_detail, score, other
except Exception as e:
print("详情页BUG")
print(url)
time.sleep(4)
return get_detail(page, url)
这个函数负责从详情页提取以下信息:
-
详细地址
-
展览时间
-
票价
-
评分(从图片URL中提取)
-
其他相关信息
如果遇到异常,会等待4秒后重试,实现了简单的错误处理机制。
3. 主运行逻辑
def run(page, url):
try:
page.get(url)
# 获取所有li元素
lis = page.eles("xpath://ul[@class='w980 pt20']/li")
# 遍历li元素
for li in lis:
href = li.ele('xpath:.//a').attr('href')
title = li.ele('xpath:.//a').attr('title')
city = li.ele('xpath:.//span[@class='w120 fl']').text.strip()
ticket_price, time_interval, address_detail, score, other = get_detail(page, href)
long_str = f"{href},{title},{city},{ticket_price},{time_interval},{address_detail},{score},{other}\n"
save(long_str)
except Exception as e:
print("列表页BUG")
print(url)
time.sleep(4)
run(page, url)
主运行函数负责:
-
访问列表页URL
-
提取所有展览项目的li元素
-
对每个展览项目提取基本信息(链接、标题、城市)
-
调用get_detail获取详细信息
-
将所有信息组合成CSV格式并保存
同样实现了错误重试机制。
4. 主程序
if __name__ == '__main__':
# 创建页面对象
page = WebPage()
# 生成URL列表
urls = [f"https://www.nyato.com/manzhan/?type=expired&p={i}" for i in range(1, 1313)]
for url in urls:
print(f"正在抓取{url}")
run(page, url)
time.sleep(random.uniform(1, 3)) # 随机延迟避免被封
print("全部爬取完毕")
page.close()
主程序创建WebPage对象,生成1312个分页URL,然后依次处理每个URL,并在每次请求间添加1-3秒的随机延迟,以降低被封禁的风险。
爬虫特点
-
健壮性:实现了简单的错误重试机制,遇到异常会等待后重试
-
反反爬:使用随机延迟模拟人类操作
-
数据完整:提取了展览的多种信息并保存为结构化数据
-
可扩展:代码结构清晰,便于添加新的数据字段或修改抓取逻辑
改进建议
-
异常处理:可以增加更详细的异常分类处理
-
日志系统:替换print为logging模块,便于问题排查
-
分布式:对于1312页的大规模抓取,可以考虑分布式架构
-
数据清洗:在保存前对数据进行清洗和验证
-
进度保存:记录已完成的页数,便于中断后恢复
总结
这个爬虫展示了如何使用DrissionPage库高效地从网站抓取结构化数据。通过合理的错误处理和反反爬策略,能够稳定地完成大规模数据采集任务。代码结构清晰,功能完整,是一个实用的网页爬虫实现。