🔗 运行环境:PYTHON
🚩 撰写作者:左手の明天
🥇 精选专栏:《python》
🔥 推荐专栏:《算法研究》
#### 防伪水印——左手の明天 ####
💗 大家好🤗🤗🤗,我是左手の明天!好久不见💗
💗今天更新系列【python网络爬虫案例】—— 爬取豆瓣电影信息💗
📆 最近更新:2024 年 08 月 04 日,左手の明天的第 344 篇原创博客
📚 更新于专栏:python网络爬虫
#### 防伪水印——左手の明天 ####
在互联网时代,信息获取变得越来越便捷。如果对电影信息感兴趣,那么可以通过Python编程语言来爬取豆瓣电影的相关信息。下面将介绍如何使用Python爬取豆瓣电影信息的步骤。
一、前言
豆瓣是一个电影资讯网站,用户可以在网站上查找电影信息、评论电影等。我们希望通过爬虫程序获取豆瓣电影的名称、评分和简介等信息,以便进行数据分析或制作推荐系统。
在Python中爬取豆瓣电影信息,我们可以使用多种库,比如requests
来发送HTTP请求,以及BeautifulSoup
或lxml
来解析HTML内容。但是,需要注意的是,豆瓣网站有反爬虫机制,频繁请求可能会被封IP。因此,在编写爬虫时应当注意请求频率,适当添加请求头,以及考虑使用代理。
二、基本开发环境
Python 3.9
Pycharm
三、相关模块的使用
from bs4 import BeautifulSoup # 网页解析,获取数据
import re # 正则表达式,进行文字匹配
import Ch # 自定义模块,提供网络请求和缓存目录获取功能
import requests # 网络
import csv #
数据交换模式,它使用逗号作为字段之间的分隔符,并以纯文本形式存储表格数据。
二、爬取豆瓣电影信息方法
2.1 明确需求
爬取豆瓣Top250排行电影信息,涉及信息包含如下:
1、电影详情;2、电影图片;3、电影名字;4、导演、主演;5、年份、国家、类型;6、评分、评价人数;7、电影简介
下面是展示几种方法展示如何使用爬取豆瓣电影Top 250的信息:
2.2 使用requests和BeautifulSoup库进行爬取
(1)爬取步骤
•使用Python的Requests库发送HTTP请求获取豆瓣电影网页的HTML源码。
•使用BeautifulSoup库解析HTML源码,提取电影名称、评分和简介等信息。
•使用数据库或文件存储提取的电影信息,以便后续使用或分析。
(2) 安装所需库
在Python中,可以使用requests库来发送HTTP请求,使用BeautifulSoup库来解析HTML页面。因此,需要先安装这两个库:
pip install requests beautifulsoup4
(3)爬取代码
# 导入必要的模块
import csv
from bs4 import BeautifulSoup
import Ch # 自定义模块,提供网络请求和缓存目录获取功能
# 主函数
def main(url):
# 使用Ch模块的get_web_request方法获取网页的HTML内容
html = Ch.get_web_request(url)
# 创建BeautifulSoup对象,用于解析HTML
soup = BeautifulSoup(html, 'html.parser')
# 获取页面上的每个.item元素(代表每部电影)
for element in soup.select('.item'):
# 获取排行榜的序号
num = element.select_one('em').text
# 获取电影名称
zw_name = element.select_one('span.title').text
# 获取电影详情链接
urls = element.select_one('div.hd a')['href']
# 获取评分
star_rating = element.select('div.star span')[1].text
# 获取评价人数,去除“人评价”文本
star_num = element.select('div.star span')[3].text.replace('人评价', '')
# 获取剧情评语,如果不存在则为空字符串
content = element.select_one('p span.inq').text if element.select_one('p span.inq') is not None else ''
# 将抓取的数据打包成元组
tuples = (num, zw_name, urls, star_rating, star_num, content)
# 将元组写入CSV文件
csv_writer.writerow(tuples)
# 打印当前处理的元组信息
print(tuples)
if __name__ == '__main__':
# 打开CSV文件,写模式,UTF-8编码,去除空行
with open(Ch.get_dir_cache_to('test.csv'), mode='w', encoding='utf-8', newline='') as f:
# 创建CSV写入器
csv_writer = csv.writer(f)
# 写入表头
csv_writer.writerow(['序号', '电影名称', '电影详情链接', '评分', '评价人数', '剧情概况'])
# 循环抓取前10页的数据
for i in range(10):
# 调用main函数,传入当前页的URL
main(f'https://movie.douban.com/top250?start={i * 25}&filter=')
# 打印完成提示
print(f'第{i + 1}页爬取完毕.')
2.3 使用XPath进行爬取
使用XPath来爬取豆瓣电影排行榜是一个常见且有效的方法,因为XPath提供了一种强大的方式来在XML和HTML文档中查找信息。
在Python中,可以结合使用requests
库来发送HTTP请求获取网页内容,以及lxml
或BeautifulSoup
库(尽管BeautifulSoup本身不直接支持XPath,但可以与lxml解析器一起使用以支持XPath)来解析HTML并应用XPath表达式提取所需的数据。
以下是一个使用requests
和lxml
(通过etree
模块)来爬取豆瓣电影Top 250排行榜的简单示例:
import requests
from lxml import etree
def get_douban_top_movies(url, page=1):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
try:
response = requests.get(url.format(page), headers=headers)
response.raise_for_status() # 如果响应状态码不是200,则引发HTTPError异常
# 使用lxml的etree解析HTML
html = etree.HTML(response.text)
# XPath表达式用于查找电影列表中的每个电影项
movie_items = html.xpath('//div[@class="item"]')
movie_list = []
for item in movie_items:
title = item.xpath('.//span[@class="title"]/text()')[0].strip()
info = item.xpath('.//div[@class="bd"]/p/text()')[0].strip()
rating, num_ratings = map(lambda x: x.strip(), info.split('/', 1))
try:
quote = item.xpath('.//span[@class="inq"]/text()')[0].strip()
except IndexError:
quote = ''
movie_list.append({
'title': title,
'rating': rating,
'num_ratings': num_ratings,
'quote': quote
})
return movie_list
except requests.RequestException as e:
print(e)
return []
if __name__ == '__main__':
url = 'https://movie.douban.com/top250?start={}&filter='
for page in range(0, 250, 25): # 豆瓣Top 250是分页的,每页25部电影
movies = get_douban_top_movies(url, page)
for movie in movies:
print(movie)
# 根据需要,可以在这里添加将数据保存到文件或数据库的逻辑
注意:
-
上述代码中的XPath表达式
//div[@class="item"]
是用来查找每部电影的容器元素。这个XPath假设豆瓣的HTML结构是这样的,但实际上这个结构可能会随着时间的推移而改变。 -
豆瓣网站有反爬虫措施,频繁请求可能会被封IP。因此,在实际应用中,你应该考虑添加请求间隔(例如使用
time.sleep()
),使用代理等策略。 -
示例中的
url.format(page)
用于构建分页的URL。豆瓣Top 250每页显示25部电影,所以你可以通过改变start
参数的值来遍历所有页面。 -
根据豆瓣的当前布局,我使用了XPath
.//span[@class="title"]/text()
来提取电影标题,.//div[@class="bd"]/p/text()
来提取评分和评分人数,以及.//span[@class="inq"]/text()
(如果存在)来提取电影简介。然而,随着网站布局的更新,这些XPath表达式可能需要调整。
2.4 使用正则表达式进行爬取
虽然正则表达式(Regular Expressions)在文本处理中非常强大,但它们通常不是解析HTML或XML文档的最佳工具,因为这些文档的结构化特性(如标签和属性)更适合使用如XPath或CSS选择器这样的解析技术。然而,如果你只是需要从一个非常简单的HTML结构或者特定模式的文本中提取数据,或者作为学习的目的,使用正则表达式也是可行的。
对于豆瓣电影排行榜,由于HTML结构相对复杂,直接使用正则表达式可能会变得非常繁琐且易出错。但是,如果我们假设某个特定部分的数据可以通过正则表达式来提取(例如,从某个JavaScript变量中直接提取JSON数据,这在某些情况下可能会发生),我们可以编写一个简化的例子。
然而,在大多数情况下,我们不会直接从HTML标签中提取信息,而是会提取一些更简单的文本模式,比如页面上的某个特定段落或链接的文本。但请注意,对于豆瓣电影排行榜这样的动态内容,数据往往是通过JavaScript动态加载的,因此直接从HTML源代码中可能找不到所有数据。
不过,为了演示如何使用正则表达式来提取一些简单信息(假设这些信息是静态的或者已经以某种方式提取到了文本中),我们可以编写一个简化的Python脚本。但请注意,这个脚本不会直接爬取豆瓣电影排行榜,因为它不会处理JavaScript加载的数据。
import re
# 假设这是从某处获取的HTML页面内容(实际上你需要使用requests库来获取它)
# 这里我们使用一个简化的字符串来模拟HTML内容
html_content = '''
<div>
<h2>电影名称1</h2>
<p>评分: 9.2</p>
<p>评价人数: 123,456</p>
</div>
<div>
<h2>电影名称2</h2>
<p>评分: 8.5</p>
<p>评价人数: 65,432</p>
</div>
'''
# 使用正则表达式提取电影名称、评分和评价人数
pattern = r'<h2>(.*?)</h2>.*?<p>评分: (\d+\.\d+)</p>.*?<p>评价人数: (\d+,\d+)</p>'
matches = re.findall(pattern, html_content, re.DOTALL)
for match in matches:
title, rating, num_ratings = match
print(f"电影名称: {title.strip()}, 评分: {rating}, 评价人数: {num_ratings}")
# 注意:这里的正则表达式和代码只是为了演示目的
# 实际上,对于复杂的HTML文档,你应该使用像BeautifulSoup或lxml这样的库
但请记住,上面的代码示例并不是用来爬取豆瓣电影排行榜的,因为它不会处理JavaScript动态加载的内容,也不会处理豆瓣网站的反爬虫机制。
对于豆瓣电影排行榜的爬取,你通常需要使用像Selenium这样的工具来模拟浏览器行为,或者分析网络请求来找到实际包含电影数据的API接口,并使用requests
库来调用这些API。同时,你还需要处理Cookie、User-Agent等HTTP头部信息,以及可能的反爬虫措施。
爬取的完整代码如下:
# 导入必要的模块
import csv
import re
from bs4 import BeautifulSoup
import Ch # 假设Ch模块提供了一些自定义功能,如网络请求和文件路径获取
# 定义主函数,负责爬取指定URL的网页数据
def main(url):
# 使用Ch模块的get_web_request方法发送网络请求并获取响应内容
html = Ch.get_web_request(url)
# 使用BeautifulSoup解析HTML内容
soup = BeautifulSoup(html, 'html.parser')
# 查找所有class为'item'的div标签,即每一部电影的条目
for item in soup.find_all('div', class_='item'):
# 使用正则表达式提取电影详情链接
info_01 = re.findall(re.compile(r'<a href="(.*?)">'), str(item))[0]
# 提取电影封面图片链接
info_02 = re.findall(re.compile(r'<img.*src="(.*?)"', re.S), str(item))[0]
# 提取电影标题(中文名和英文名),可能有两个标题
title = re.findall(re.compile(r'<span class="title">(.*)</span>'), str(item))
# 根据标题数量,设置中文名和外文名
if len(title) == 2:
info_03 = title[0] # 中文名
info_04 = title[1].replace('/', '') # 英文名,去除斜杠
else:
info_03 = title[0] # 中文名
info_04 = ' ' # 如果只有一个标题,英文名留空
# 提取评分
info_05 = re.findall(re.compile(r'<span class="rating_num" property="v:average">(.*)</span>'), str(item))[0]
# 提取评价人数
info_06 = re.findall(re.compile(r'<span>(\d*)人评价</span>'), str(item))[0]
# 提取剧情概况,可能不存在
inq = re.findall(re.compile(r'<span class="inq">(.*)</span>'), str(item))
if len(inq) == 0:
info_07 = ' ' # 如果没有概况,留空
else:
info_07 = inq[0].replace('。', '') # 去除句点
# 提取更多信息,如导演、演员等,可能存在换行和斜杠
bd = re.findall(re.compile(r'<p class="">(.*?)</p>', re.S), str(item))[0]
# 清理换行符和多余空格
bd = re.sub('<br(\s+)?/>(\s+)?', '', bd)
bd = re.sub('/', '', bd)
info_08 = bd.strip() # 去除首尾空格
# 将提取的信息打包成元组
tuples = (info_01, info_02, info_03, info_04, info_05, info_06, info_07, info_08)
# 将元组写入CSV文件
csv_writer.writerow(tuples)
# 打印当前处理的元组信息
print(tuples)
if __name__ == '__main__':
# 打开CSV文件,写模式,UTF-8编码,无空行
with open(Ch.get_dir_cache_to('test.csv'), mode='w', encoding='utf-8', newline='') as f:
# 创建CSV写入器
csv_writer = csv.writer(f)
# 写入表头
csv_writer.writerow(['电影详情链接', '图片链接', '影片中文名', '影片外国名', '评分', '评价人数', '剧情概况', '相关信息'])
# 循环爬取10页数据
for i in range(10):
# 调用main函数,传入当前页的URL
main(f'https://movie.douban.com/top250?start={i * 25}&filter=')
# 打印完成提示
print(f'第{i + 1}页爬取完毕.')