Python爬虫实战:Xpath解析豆瓣Top250电影数据并构建本地数据库
1. 项目背景与准备工作豆瓣电影Top250榜单是许多影迷和数据分析爱好者经常参考的优质电影列表。作为一个Python初学者你可能经常听到爬虫这个词但不知道如何实际应用。这次我们就用最基础的requests和lxml库来完整实现一个能自动采集所有250部电影信息并建立本地数据库的实用项目。在开始之前你需要确保电脑上已经安装好Python环境建议3.6以上版本。打开命令行窗口用pip安装这两个必备库pip install requests lxmlrequests库负责网络请求就像你的网络浏览器一样去获取网页内容lxml库则是处理HTML文档的利器特别是它的Xpath功能能像GPS导航一样精准定位页面中的任何数据。我刚开始学爬虫时最头疼的就是HTML文档像一团乱麻直到学会了Xpath才发现原来数据提取可以如此简单。2. 分析网页结构与URL规律2.1 页面结构观察首先打开豆瓣Top250页面你会看到整齐排列的电影信息。每部电影都包含中英文片名比如《肖申克的救赎》和The Shawshank Redemption导演和主演信息上映年份、国家和类型评分和评价人数右键点击页面选择检查打开开发者工具。在Elements面板中你会发现每个电影条目都被包裹在li标签内而所有25部电影又都被包含在一个ol classgrid_view的大容器里。这种清晰的层级结构对我们后续写Xpath非常有利。2.2 URL翻页机制滚动到页面底部注意观察分页器的URL变化第一页https://movie.douban.com/top250第二页https://movie.douban.com/top250?start25filter第三页https://movie.douban.com/top250?start50filter发现规律了吗start参数每次增加25正好对应每页显示的电影数量。所以我们可以用range(0, 250, 25)来生成所有页面的URL。这个小技巧在我第一次爬豆瓣时花了半天才想明白现在你可以直接拿来用了。3. 编写爬虫核心代码3.1 基础请求设置先设置请求头这是模拟浏览器访问的关键。豆瓣对没有User-Agent的请求会直接拒绝headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 }然后构造URL参数。这里有个小优化直接把参数拼接到URL里比用data参数更直观base_url https://movie.douban.com/top250 params {start: 0, filter: }3.2 Xpath定位技巧这才是最精彩的部分通过开发者工具我们可以轻松复制Xpath右键点击电影标题 - 检查 - 右键对应HTML元素 - Copy - Copy XPath你会得到类似这样的路径//*[idcontent]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]但直接使用这个Xpath有两个问题它只匹配第一部电影(li[1])路径太长容易出错我推荐更简洁的写法# 获取所有电影条目 movies html.xpath(//ol[classgrid_view]/li) # 在单个电影内相对定位 for movie in movies: title_cn movie.xpath(.//span[classtitle][1]/text())[0] title_en movie.xpath(.//span[classtitle][2]/text())[0].replace(\xa0, )注意那个点(.)表示从当前节点开始查找这是Xpath的相对路径写法能避免很多定位错误。3.3 数据清洗实战原始数据往往包含各种杂质比如英文名中的\xa0特殊字符导演和主演信息混在一起年份、国家、类型用斜杠连接处理这些数据的小技巧# 处理导演和主演 info movie.xpath(.//div[classbd]/p[1]/text())[0].strip() director info.split(\xa0\xa0\xa0)[0].replace(导演: , ) actors info.split(\xa0\xa0\xa0)[1].replace(主演: , ) if len(info.split(\xa0\xa0\xa0)) 1 else # 处理年份国家类型 year_info movie.xpath(.//div[classbd]/p[1]/text()[2])[0].strip() year, country, genre [x.strip() for x in year_info.split(\xa0/\xa0)]4. 数据存储与完整实现4.1 CSV存储优化使用csv模块时建议用with语句自动关闭文件避免数据丢失import csv with open(douban_top250.csv, w, encodingutf-8-sig, newline) as f: writer csv.writer(f) writer.writerow([中文名,英文名,导演,主演,年份,国家,类型,评分,评价人数]) # 写入数据...注意utf-8-sig编码可以解决Excel打开中文乱码的问题这是我在实际项目中踩过的坑。4.2 完整代码结构把上面的知识点整合起来完整的爬虫应该包含请求函数处理网络异常解析函数用try避免某条数据解析失败影响整体存储函数主循环控制翻页import requests from lxml import etree import csv from time import sleep def get_page(url): try: response requests.get(url, headersheaders) if response.status_code 200: return response.text except requests.RequestException: return None def parse_page(html): # 解析逻辑... return movie_data def save_to_csv(data): # 存储逻辑... def main(): for i in range(0, 250, 25): url fhttps://movie.douban.com/top250?start{i} html get_page(url) if html: data parse_page(html) save_to_csv(data) sleep(2) # 礼貌性延迟 if __name__ __main__: main()5. 反爬策略与项目扩展5.1 应对反爬机制豆瓣虽然不像某些网站反爬那么严格但还是有些小技巧要注意随机延迟用random.uniform(1,3)替代固定sleep时间代理IP如果频繁被封可以考虑使用代理池更换User-Agent准备多个浏览器标识随机切换5.2 项目扩展方向这个基础项目完成后你还可以爬取每部电影的详情页获取更多信息剧情简介、短评等用pandas分析评分分布、导演作品数量等制作可视化图表展示分析结果用SQLite替代CSV建立真正的本地数据库记得我第一次完整跑通这个爬虫时看到CSV里整齐的电影数据特别有成就感。现在你可能觉得Xpath有点复杂但多练习几次就会发现它的规律。爬虫最有趣的地方在于每个网站都像是一个新的谜题而Xpath就是你解开谜题的钥匙。