使用Python实现一个简单的Web爬虫
在当今互联网时代,数据是无处不在的。从社交媒体到电子商务网站,各种信息都隐藏在网络中等待被挖掘。为了获取这些数据,我们经常使用网络爬虫(Web Crawler)技术来自动抓取网页内容。本文将介绍如何使用Python编写一个简单的Web爬虫,并展示其基本原理和实际应用。
我们将使用requests
库来发送HTTP请求,并用BeautifulSoup
解析HTML文档。最后,我们还会将爬取的数据保存为CSV文件。
准备工作
1. 安装所需库
首先确保你已经安装了以下Python库:
pip install requests beautifulsoup4 lxml pandas
requests
:用于发送HTTP请求。beautifulsoup4
:用于解析HTML文档。lxml
:作为BeautifulSoup的解析器,速度快。pandas
:用于数据处理与保存。爬虫的基本结构
一个基础的爬虫通常包括以下几个步骤:
发送HTTP请求获取网页内容;解析HTML内容,提取目标数据;存储或处理提取到的数据;遵守网站的robots.txt规则,避免频繁访问造成负担。实战:爬取豆瓣电影Top250榜单
我们将以豆瓣电影Top250为例,爬取每部电影的名称、评分、导演、年份、国家和类型等信息。
1. 发送请求并获取页面内容
import requestsfrom bs4 import BeautifulSoupimport timeimport randomdef get_html(url): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0 Safari/537.36' } try: response = requests.get(url, headers=headers) if response.status_code == 200: return response.text else: print(f"请求失败,状态码:{response.status_code}") return None except Exception as e: print("请求出错:", e) return None
2. 解析HTML并提取电影信息
def parse_html(html): soup = BeautifulSoup(html, 'lxml') items = soup.find_all('div', class_='item') movies = [] for item in items: rank = item.find('em').text.strip() title = item.find('span', class_='title').text.strip() rating = item.find('span', class_='rating_num').text.strip() info = item.find('div', class_='bd').p.text.strip().split('\n') director_and_year = info[0].strip().replace(' ', '').split('...') director = director_and_year[0][3:] # 去掉导演前面的“导演:” year = director_and_year[-1] country_genre = info[1].strip().split('/') country = country_genre[0] genre = '/'.join(country_genre[1:]).strip() movie_data = { '排名': rank, '片名': title, '评分': rating, '导演': director, '年份': year, '国家': country, '类型': genre } movies.append(movie_data) return movies
3. 爬取所有页面(分页)
豆瓣Top250是分页的,每页显示25条记录,共10页。
def crawl_douban_top250(): base_url = "https://movie.douban.com/top250?start=" all_movies = [] for i in range(0, 250, 25): url = base_url + str(i) html = get_html(url) if html: movies = parse_html(html) all_movies.extend(movies) print(f"已爬取第 {i // 25 + 1} 页,共 {len(movies)} 条电影数据") time.sleep(random.uniform(1, 3)) # 模拟人类访问间隔 else: break return all_movies
4. 保存为CSV文件
import pandas as pddef save_to_csv(data, filename='douban_top250.csv'): df = pd.DataFrame(data) df.to_csv(filename, index=False, encoding='utf-8-sig') print(f"数据已成功保存至 {filename}")
5. 主函数调用
if __name__ == '__main__': data = crawl_douban_top250() save_to_csv(data)
完整代码整合
以下是完整的Python脚本:
import requestsfrom bs4 import BeautifulSoupimport timeimport randomimport pandas as pddef get_html(url): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0 Safari/537.36' } try: response = requests.get(url, headers=headers) if response.status_code == 200: return response.text else: print(f"请求失败,状态码:{response.status_code}") return None except Exception as e: print("请求出错:", e) return Nonedef parse_html(html): soup = BeautifulSoup(html, 'lxml') items = soup.find_all('div', class_='item') movies = [] for item in items: rank = item.find('em').text.strip() title = item.find('span', class_='title').text.strip() rating = item.find('span', class_='rating_num').text.strip() info = item.find('div', class_='bd').p.text.strip().split('\n') director_and_year = info[0].strip().replace(' ', '').split('...') director = director_and_year[0][3:] # 去掉导演前面的“导演:” year = director_and_year[-1] country_genre = info[1].strip().split('/') country = country_genre[0] genre = '/'.join(country_genre[1:]).strip() movie_data = { '排名': rank, '片名': title, '评分': rating, '导演': director, '年份': year, '国家': country, '类型': genre } movies.append(movie_data) return moviesdef crawl_douban_top250(): base_url = "https://movie.douban.com/top250?start=" all_movies = [] for i in range(0, 250, 25): url = base_url + str(i) html = get_html(url) if html: movies = parse_html(html) all_movies.extend(movies) print(f"已爬取第 {i // 25 + 1} 页,共 {len(movies)} 条电影数据") time.sleep(random.uniform(1, 3)) # 模拟人类访问间隔 else: break return all_moviesdef save_to_csv(data, filename='douban_top250.csv'): df = pd.DataFrame(data) df.to_csv(filename, index=False, encoding='utf-8-sig') print(f"数据已成功保存至 {filename}")if __name__ == '__main__': data = crawl_douban_top250() save_to_csv(data)
注意事项与合法性
虽然网络爬虫是一个非常强大的工具,但我们在使用时也需要注意以下几点:
遵守Robots协议:检查目标网站根目录下的robots.txt
文件,确认是否允许爬虫访问相关路径。设置合理的请求频率:避免对服务器造成过大压力,使用随机延迟。尊重版权和隐私:不要爬取涉及用户隐私或其他受保护的内容。使用合法的User-Agent:模拟真实浏览器行为,减少被封IP的风险。总结
本文通过一个完整的示例,演示了如何使用Python构建一个简单的Web爬虫程序。我们使用了requests
发起请求,BeautifulSoup
解析HTML,最后使用pandas
保存数据为CSV格式。整个过程展示了爬虫的基本流程和技术要点。
随着经验的积累,你可以进一步扩展这个爬虫系统,比如添加代理IP支持、多线程并发、数据库存储等功能,甚至构建一个完整的数据采集平台。
如果你对网络爬虫感兴趣,欢迎继续深入学习Scrapy框架、Selenium自动化测试等更高级的技术!
附录:运行结果示例
运行上述程序后,将在当前目录生成一个名为douban_top250.csv
的文件,内容如下:
排名 | 片名 | 评分 | 导演 | 年份 | 国家 | 类型 |
---|---|---|---|---|---|---|
1 | 肖申克的救赎 | 9.7 | 弗兰克·德拉邦特 | 1994 | 美国 | 剧情 / 犯罪 |
2 | 霸王别姬 | 9.6 | 陈凯歌 | 1993 | 中国大陆 / 香港 | 剧情 / 爱情 / 同性 |
如需获取完整源码,请复制以上代码粘贴至.py
文件中即可运行。