|
|
|
@ -0,0 +1,120 @@
|
|
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
import time
|
|
|
|
|
from wsgiref import headers
|
|
|
|
|
import requests # 导入requests库,用于发送HTTP请求
|
|
|
|
|
from bs4 import BeautifulSoup # 导入BeautifulSoup库,用于解析HTML
|
|
|
|
|
from fake_useragent import UserAgent # 导入UserAgent,用于生成随机的User-Agent
|
|
|
|
|
from openpyxl import Workbook, load_workbook # 导入openpyxl库,用于操作Excel文件
|
|
|
|
|
|
|
|
|
|
# 定义一个函数,用于获取单个页面的电影列表
|
|
|
|
|
def getonepagelist(url, headers):
|
|
|
|
|
try:
|
|
|
|
|
# 发送HTTP GET请求
|
|
|
|
|
r = requests.get(url, headers=headers, timeout=10)
|
|
|
|
|
r.raise_for_status() # 如果响应状态码不是200,则抛出异常
|
|
|
|
|
r.encoding = 'utf-8' # 设置响应内容的编码为utf-8
|
|
|
|
|
soup = BeautifulSoup(r.text, 'html.parser') # 使用BeautifulSoup解析HTML
|
|
|
|
|
lsts = soup.find_all(attrs={'class': 'hd'}) # 查找所有class为'hd'的元素,即电影列表项
|
|
|
|
|
# 遍历电影列表项
|
|
|
|
|
for lst in lsts:
|
|
|
|
|
href = lst.a['href'] # 获取电影详情页链接
|
|
|
|
|
# 从 BeautifulSoup 解析出的 HTML 元素 lst 中提取链接地址。lst.a 选择了 lst 元素内的 <a> 标签,
|
|
|
|
|
# 而 ['href'] 则提取了该 <a> 标签的 href 属性,即链接地址。这样,变量 href 就存储了提取出的链接地址。
|
|
|
|
|
time.sleep(0.5) # 休眠0.5秒,防止访问频率过高被封IP
|
|
|
|
|
getfilminfo(href, headers)
|
|
|
|
|
except: # 捕获所有异常
|
|
|
|
|
print('getonepagelist error!') # 打印错误信息
|
|
|
|
|
|
|
|
|
|
# 定义一个函数,用于获取电影详情信息
|
|
|
|
|
#注意国家/地区的处理,为了数据分析更方便,这里时长只取电影的第一个时长(部分电影有多个时长)
|
|
|
|
|
def getfilminfo(url, headers):
|
|
|
|
|
filminfo = [] # 初始化电影信息列表
|
|
|
|
|
r = requests.get(url, headers=headers, timeout=10) # 发送HTTP GET请求
|
|
|
|
|
r.raise_for_status() # 如果响应状态码不是200,则抛出异常
|
|
|
|
|
r.encoding = 'utf-8' # 设置响应内容的编码为utf-8
|
|
|
|
|
soup = BeautifulSoup(r.text, 'html.parser') # 使用BeautifulSoup解析HTML
|
|
|
|
|
# 获取电影名称
|
|
|
|
|
# 使用 BeautifulSoup 的 find 方法来找到 HTML 标签中 property 属性为 'v:itemreviewed' 的元素,通常这个元素包含电影的名称。
|
|
|
|
|
# 然后通过 .text 获取其文本内容,并使用 split(' ') 将名称以空格分割成列表,取列表的第一个元素即为电影名称。
|
|
|
|
|
name = soup.find(attrs={'property': 'v:itemreviewed'}).text.split(' ')[0]
|
|
|
|
|
# 获取上映年份
|
|
|
|
|
# 找到 HTML 标签中 class 属性为 'year' 的元素,通常包含电影的上映年份。然后使用 .text 获取文本内容,并通过 replace 方法去掉括号。
|
|
|
|
|
year = soup.find(attrs={'class': 'year'}).text.replace('(', '').replace(')', '')
|
|
|
|
|
# 获取评分
|
|
|
|
|
# 找到 HTML 标签中 property 属性为 'v:average' 的元素,通常包含电影的评分。
|
|
|
|
|
score = soup.find(attrs={'property': 'v:average'}).text
|
|
|
|
|
# 获取评价人数
|
|
|
|
|
# 找到 HTML 标签中 property 属性为 'v:votes' 的元素,通常包含电影的评价人数。
|
|
|
|
|
votes = soup.find(attrs={'property': 'v:votes'}).text
|
|
|
|
|
infos = soup.find(attrs={'id': 'info'}).text.split('\n')[1:11] # 获取电影详细信息
|
|
|
|
|
# 获取导演、编剧、主演、类型、国家/地区、语言等信息
|
|
|
|
|
# 通过列表切片和字符串处理,提取了导演、编剧、主演、类型、国家/地区等信息。
|
|
|
|
|
director = infos[0].split(': ')[1]
|
|
|
|
|
scriptwriter = infos[1].split(': ')[1]
|
|
|
|
|
actor = infos[2].split(': ')[1]
|
|
|
|
|
filmtype = infos[3].split(': ')[1]
|
|
|
|
|
area = infos[4].split(': ')[1]
|
|
|
|
|
# 用来处理国家/地区和语言信息的格式,因为有时候这些信息会以字符串列表的形式呈现,需要进行额外的处理。
|
|
|
|
|
if '.' in area: # 处理国家/地区和语言的格式
|
|
|
|
|
area = infos[5].split(': ')[1].split(' / ')[0]
|
|
|
|
|
language = infos[6].split(': ')[1].split(' / ')[0]
|
|
|
|
|
else:
|
|
|
|
|
area = infos[4].split(': ')[1].split(' / ')[0]
|
|
|
|
|
language = infos[5].split(': ')[1].split(' / ')[0]
|
|
|
|
|
|
|
|
|
|
# 对国家/地区进行处理
|
|
|
|
|
if '大陆' in area or '香港' in area or '台湾' in area:
|
|
|
|
|
area = '中国'
|
|
|
|
|
if '戛纳' in area:
|
|
|
|
|
area = '法国'
|
|
|
|
|
# 获取电影时长
|
|
|
|
|
# 到 HTML 标签中 property 属性为 'v:runtime' 的元素,通常包含电影的时长。然后使用正则表达式 re.findall('\\d+', times0)
|
|
|
|
|
# 找到文本中的数字部分,并取第一个数字,即电影的时长。
|
|
|
|
|
times0 = soup.find(attrs={'property': 'v:runtime'}).text
|
|
|
|
|
times = re.findall('\\d+', times0)[0]
|
|
|
|
|
# 将获取的信息添加到电影信息列表中
|
|
|
|
|
filminfo.append(name)
|
|
|
|
|
filminfo.append(year)
|
|
|
|
|
filminfo.append(score)
|
|
|
|
|
filminfo.append(votes)
|
|
|
|
|
filminfo.append(director)
|
|
|
|
|
filminfo.append(scriptwriter)
|
|
|
|
|
filminfo.append(actor)
|
|
|
|
|
filminfo.append(filmtype)
|
|
|
|
|
filminfo.append(area)
|
|
|
|
|
filminfo.append(language)
|
|
|
|
|
filminfo.append(times)
|
|
|
|
|
filepath = 'TOP250.xlsx' # Excel文件路径
|
|
|
|
|
insert2excel(filepath, filminfo) # 将电影信息插入到Excel文件中
|
|
|
|
|
|
|
|
|
|
# 定义一个函数,用于将电影信息插入到Excel文件中
|
|
|
|
|
# 这里我们使用openpyxl将数据保存到Excel中
|
|
|
|
|
def insert2excel(filepath, allinfo):
|
|
|
|
|
try:
|
|
|
|
|
if not os.path.exists(filepath): # 如果Excel文件不存在,则创建一个新的文件并添加表头
|
|
|
|
|
tableTitle = ['片名', '上映年份', '评分', '评价人数', '导演', '编剧', '主演', '类型', '国家/地区', '语言', '时长(分钟)']
|
|
|
|
|
wb = Workbook() # 创建一个Workbook对象
|
|
|
|
|
ws = wb.active # 获取当前活动的工作表
|
|
|
|
|
ws.title = 'sheet1' # 设置工作表的标题为'sheet1'
|
|
|
|
|
ws.append(tableTitle) # 添加表头
|
|
|
|
|
wb.save(filepath) # 保存Excel文件
|
|
|
|
|
time.sleep(3) # 休眠3秒
|
|
|
|
|
wb = load_workbook(filepath) # 加载Excel文件
|
|
|
|
|
ws = wb.active # 获取当前活动的工作表
|
|
|
|
|
ws.title = 'sheet1' # 设置工作表的标题为'sheet1'
|
|
|
|
|
ws.append(allinfo) # 添加电影信息
|
|
|
|
|
wb.save(filepath) # 保存Excel文件
|
|
|
|
|
return True # 返回True,表示插入成功
|
|
|
|
|
except:
|
|
|
|
|
return False # 返回False,表示插入失败
|
|
|
|
|
|
|
|
|
|
# 遍历爬取前11页的电影信息
|
|
|
|
|
for i in range(11):
|
|
|
|
|
print(f'正在爬取第{i}页,请稍等...')
|
|
|
|
|
url = 'https://movie.douban.com/top250?start={}&filter='.format(i * 25) # 构造URL
|
|
|
|
|
headers = {
|
|
|
|
|
'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/1'
|
|
|
|
|
} # 构造HTTP请求头部信息
|
|
|
|
|
getonepagelist(url, headers) # 调用函数获取电影列表
|
|
|
|
|
|