使用Python进行Web数据抓取:技术详解与实战示例
在当今大数据时代,网络爬虫(Web Scraping) 已成为获取互联网信息的重要手段之一。无论是用于市场分析、舆情监控还是学术研究,网络爬虫都发挥着不可或缺的作用。本文将详细介绍如何使用 Python 编写一个简单的网页数据抓取程序,并结合实际案例展示其应用。
什么是网络爬虫?
网络爬虫(Web Crawler),也称为网页蜘蛛或网络机器人,是一种自动下载并解析网页内容的程序。它的核心功能包括:
发送HTTP请求获取网页HTML解析HTML文档提取目标数据存储数据到本地文件或数据库中为什么选择Python?
Python 是目前最流行的网络爬虫开发语言之一,原因如下:
简洁易读的语法,适合快速开发强大的第三方库支持(如requests
, BeautifulSoup
, Scrapy
, Selenium
)社区活跃,资源丰富爬虫基本流程
发送请求:使用requests
或 urllib
库向目标网站发起 HTTP 请求。解析页面:使用 BeautifulSoup
或 lxml
解析 HTML 页面结构。提取数据:根据 HTML 标签和属性定位所需数据。存储数据:将数据保存为 JSON、CSV 或数据库格式。实战案例:抓取豆瓣电影 Top 250 的电影名称和评分
我们将以 豆瓣电影 Top 250 为例,编写一个 Python 脚本抓取每部电影的名称和评分。
4.1 安装依赖库
首先确保安装了以下 Python 库:
pip install requests beautifulsoup4 lxml
4.2 编写代码
import requestsfrom bs4 import BeautifulSoupimport csv# 设置请求头,模拟浏览器访问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'}# 获取单页内容def get_page(url): response = requests.get(url, headers=headers) if response.status_code == 200: return response.text else: print(f"请求失败,状态码:{response.status_code}") return None# 解析单页内容def parse_page(html): soup = BeautifulSoup(html, 'lxml') items = soup.find_all('div', class_='item') for item in items: rank = item.find('em').text.strip() title = item.find('span', class_='title').text.strip() rating_tag = item.find('span', class_='rating_num') rating = rating_tag.text.strip() if rating_tag else '暂无评分' yield { '排名': rank, '电影名': title, '评分': rating }# 保存为CSV文件def save_to_csv(data, filename='douban_top250.csv'): with open(filename, mode='w', encoding='utf-8-sig', newline='') as f: writer = csv.DictWriter(f, fieldnames=['排名', '电影名', '评分']) writer.writeheader() writer.writerows(data)# 主函数def main(): base_url = "https://movie.douban.com/top250" all_data = [] for i in range(0, 250, 25): # 每页25条数据,共10页 url = f"{base_url}?start={i}" html = get_page(url) if html: data = list(parse_page(html)) all_data.extend(data) print(f"第 {i//25 + 1} 页数据已抓取完成,共 {len(data)} 条记录") save_to_csv(all_data) print("所有数据已保存完毕!")if __name__ == '__main__': main()
代码解析说明
5.1 请求部分
我们使用 requests.get()
向豆瓣电影 Top 250 页面发送 GET 请求。设置 User-Agent
是为了防止被服务器识别为爬虫而拒绝访问。
5.2 解析部分
通过 BeautifulSoup
和 lxml
解析器,我们可以轻松地从 HTML 中提取结构化数据。例如:
find_all('div', class_='item')
:找到所有电影条目。find('span', class_='title')
:获取电影标题。find('span', class_='rating_num')
:获取评分。5.3 数据存储
我们使用 csv.DictWriter
将数据写入 CSV 文件,字段包括“排名”、“电影名”和“评分”。使用 utf-8-sig
编码是为了避免 Excel 打开时出现乱码。
注意事项与反爬机制应对策略
虽然我们完成了基本的数据抓取,但在实际应用中还需注意以下问题:
6.1 遵守 robots.txt 协议
每个网站根目录下通常有 robots.txt
文件,定义哪些路径可以被抓取。例如豆瓣的 robots.txt 地址是:https://www.douban.com/robots.txt
6.2 设置请求间隔
频繁请求容易触发网站的反爬机制,建议在每次请求之间加入随机延迟:
import timeimport randomtime.sleep(random.uniform(1, 3)) # 每次请求间隔1~3秒
6.3 使用代理 IP
如果遇到 IP 被封的情况,可以使用代理服务轮换 IP 地址:
proxies = { 'http': 'http://user:pass@ip:port', 'https': 'http://user:pass@ip:port'}requests.get(url, proxies=proxies)
进阶推荐:使用 Scrapy 框架
对于更复杂的爬虫项目,建议使用 Scrapy 框架。它提供了完整的爬虫架构,包括中间件、管道、日志等功能,适合构建大规模数据采集系统。
本文介绍了使用 Python 抓取网页数据的基本方法,并通过豆瓣电影 Top 250 的实战案例演示了整个流程。掌握这些技能后,你可以尝试爬取新闻、商品价格、股票数据等各类公开信息。
随着你对网络爬虫的理解加深,也可以进一步学习动态页面处理(如 Selenium)、分布式爬虫(如 Scrapy-Redis)等高级主题。
附录:完整代码一览
import requestsfrom bs4 import BeautifulSoupimport csvimport timeimport randomheaders = { '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'}def get_page(url): response = requests.get(url, headers=headers) if response.status_code == 200: return response.text else: print(f"请求失败,状态码:{response.status_code}") return Nonedef parse_page(html): soup = BeautifulSoup(html, 'lxml') items = soup.find_all('div', class_='item') for item in items: rank = item.find('em').text.strip() title = item.find('span', class_='title').text.strip() rating_tag = item.find('span', class_='rating_num') rating = rating_tag.text.strip() if rating_tag else '暂无评分' yield { '排名': rank, '电影名': title, '评分': rating }def save_to_csv(data, filename='douban_top250.csv'): with open(filename, mode='w', encoding='utf-8-sig', newline='') as f: writer = csv.DictWriter(f, fieldnames=['排名', '电影名', '评分']) writer.writeheader() writer.writerows(data)def main(): base_url = "https://movie.douban.com/top250" all_data = [] for i in range(0, 250, 25): url = f"{base_url}?start={i}" html = get_page(url) if html: data = list(parse_page(html)) all_data.extend(data) print(f"第 {i//25 + 1} 页数据已抓取完成,共 {len(data)} 条记录") time.sleep(random.uniform(1, 3)) save_to_csv(all_data) print("所有数据已保存完毕!")if __name__ == '__main__': main()
如需进一步扩展此项目,可添加更多字段(如导演、年份、类型等),或将数据导入 MySQL、MongoDB 等数据库中。欢迎继续探索 Python 网络爬虫的世界!