第一步,利用selenium爬虫
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from lxml import etree
from tkinter import *
import warnings
warnings.filterwarnings('ignore')
import json
import pandas as pd
import time
option = webdriver.ChromeOptions()
option.add_argument('disable-infobars')
option.add_argument('--headless') # 隐藏窗口
browser = webdriver.Chrome(chrome_options=option)
browser_detail = webdriver.Chrome(chrome_options=option)
browser.maximize_window()
wait = WebDriverWait(browser, 10)
keyword = '韩剧'
rank = 'recommend'
global click_times
click_times = 5
all_directors = []
all_actors = []
all_stars5_rate = []
def login():
#页面加载
login_url = 'https://accounts.douban.com/passport/login'
browser.get(login_url)
login_handle = browser.current_window_handle
# print(login_handle)
submit = wait.until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
'.account-tab-account'
))
)
submit.click()
user_name = wait.until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
'#username')))
password = wait.until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
'#password'
))
)
submit = wait.until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
'a.btn:nth-child(1)'
))
)
#输入登陆账号信息
user_name.send_keys('#####')
password.send_keys('#####')
#模拟登陆
submit.click()
return login_handle
def index(login_handle):
cookies = browser.get_cookies()
# print(cookies)
url = 'https://movie.douban.com/tv/#!type=tv&tag=' + keyword + '&sort=' + rank + '&page_limit=20&page_start=0'
js = 'window.open("{}");'.format(url)
browser.execute_script(js)
browser.get(url)
# index_handle = browser.current_window_handle
windows = browser.window_handles
browser.switch_to_window(windows[1])
browser.close()
browser.switch_to_window(windows[0])
time.sleep(3)
#点击加载更多
# global click_times
# click_times = 4
for i in range(click_times):
more = wait.until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
'#content > div > div.article > div > div.list-wp > a'
))
)
browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
time.sleep(2)
more.click()
html = browser.page_source
return html
def parse_index(html):
etree_html = etree.HTML(html)
names = etree_html.xpath('//div[@class="list-wp"]/div[@class="list"]/a[@class="item"]/div[@class="cover-wp"]/img/@alt')
scores = etree_html.xpath('//div[@class="list-wp"]/div[@class="list"]/a[@class="item"]/p/strong/text()')
href = etree_html.xpath('//div[@class="list-wp"]/div[@class="list"]/a[@class="item"]/@href')
df = pd.DataFrame({'names': names, 'scores': scores})
df['scores'] = pd.to_numeric(df['scores'])
return href, df
def detail(href):
for i in range(click_times * 20):
print('正在解析第', str(i+1), '部剧')
director_list = []
actor_list = []
url = href[i]
if url:
# js = 'window.open("{}");'.format(url)
# browser.execute_script(js)
# windows = browser.window_handles
browser_detail.get(url)
html = browser_detail.page_source
# browser.switch_to_window(windows[0])
# print(html)
compile1 = re.compile(r'<script type="application/ld\+json">(.*?)</script>', re.S)
html0 = re.findall(compile1, html)[0]
data = json.loads(html0, strict=False)
# print(data)
if data and 'director' in data.keys(): # 导演
# print(data.get('director'))
for item in data.get('director'):
# print(item.get('name'))
director_list.append(item.get('name').split()[0])
# print(director_list)
all_directors.append(director_list)
if data and 'actor' in data.keys(): # 演员
# print(data.get('actor'))
for item in data.get('actor'):
# print(item.get('name'))
actor_list.append(item.get('name').split()[0])
print(actor_list)
all_actors.append(actor_list)
etree_html = etree.HTML(html)
stars5_rate = etree_html.xpath('//div[@class="ratings-on-weight"]//span[@class="rating_per"]/text()')[0]
all_stars5_rate.append(stars5_rate)
else:
all_directors.append([])
all_actors.append([])
all_stars5_rate.append([])
actors_df = pd.DataFrame({'actors': all_actors})
director_df = pd.DataFrame({'directors': all_directors})
stars5_df = pd.DataFrame({'star5_rate': all_stars5_rate})
return actors_df, director_df, stars5_df
def main():
start_time = time.time()
login_handle = login()
html = index(login_handle)
# print(html)
href, df = parse_index(html)
actors_df, director_df, stars5_df = detail(href)
concat_df = pd.concat([df, stars5_df, actors_df, director_df], axis=1)
print(concat_df.head(10))
concat_df.to_csv('douban_scrapy.csv', encoding='utf_8_sig')
browser.close()
browser.quit()
waiste_time = time.time() - start_time
print('此次爬虫用时:', waiste_time)
if __name__ == '__main__':
main()
第二步,导入数据开始分析
# 导入相关包
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
import collections
import wordcloud
from PIL import Image
import seaborn as sns
%matplotlib inline
import matplotlib
import re
pd.set_option('display.max_row', 100)
pd.set_option('display.max_colwidth', 100)
# 读取数据,查看数据,修改数据
data = pd.read_csv('./Desktop/douban_scrapy.csv').iloc[:,1:]
data.info()
# 修改数据类型
data['star5_rate'] = data['star5_rate'].apply(lambda x: float(x.replace('%', '')))
# 按五星好评率和评分降序排列
df_sortByScores = data.sort_values(['star5_rate', 'scores'], ascending=False)
df_sortByScores.head()
前100部热门韩剧总体情况
# 前100个样本,平均评分为8.215,平均五星好评率为41.83%,最高评分为9分,最低得分为5分。
df_sortByScores.describe()

评分情况分析
# 找出最高评分和最低评分的韩剧名称。
print('评分最高的电视剧及其评分:', '\n',
'名称:', df_sortByScores[df_sortByScores['scores'] == df_sortByScores['scores'].max()]['names'].tolist()[0],
'\n',
'评分:', df_sortByScores['scores'].max(),
'\n')
print('评分最低的电视剧及其评分:', '\n',
'名称:', df_sortByScores[df_sortByScores['scores'] == df_sortByScores['scores'].min()]['names'].tolist()[0],
'\n',
'评分:', df_sortByScores['scores'].min())
# 打印信息:
评分最高的电视剧及其评分:
名称: 请回答1988
评分: 9.7
评分最低的电视剧及其评分:
名称: 河伯的新娘2017
评分: 5.0
# 评分分布情况,50%的评分在8.3以上。
plt.figure(figsize=(18, 8))
sns.countplot(x='scores', data=df_sortByScores)
plt.tick_params(labelsize=10)
plt.savefig('/Users/mac/Desktop/评分分布.jpg')

# 评分区间占比
pie_data = df_sortByScores.iloc[:, 0:3]
scores_bins = np.arange(0, 11, 1)
pie_data['scores_cut'] = pd.cut(pie_data['scores'], scores_bins)
pie_data['scores_cut'] = pie_data['scores_cut'].astype('str')
scores_label = pie_data['scores_cut'].value_counts().index.tolist()
scores_counter = pie_data['scores_cut'].value_counts().values.tolist()
plt.figure(figsize=(10,10))
plt.pie(scores_counter, labels=scores_label, autopct='%1.1f%%')
plt.savefig('/Users/mac/Desktop/评分区间占比.jpg')

# 根据评分透视电视剧,并按评分降序排列
df_sortByScores[['scores', 'names']].pivot_table(index='scores', aggfunc=lambda x: ', '.join(x)).sort_values(['scores'], ascending=False)


五星好评率情况分析
# 五星好评率大于50的韩剧数量,一共有29部。
star5_rate_count = collections.Counter(df_sortByScores['star5_rate'])
# star5_rate_count
star5_rate_count_df = pd.DataFrame({'star5_rate': list(star5_rate_count.keys()),
'star5_rate_count': list(star5_rate_count.values())})
# star5_rate_count_df.info()
star5_rate_moreThan50 = star5_rate_count_df[star5_rate_count_df['star5_rate'] >= 50].shape[0]
print('五星好评率大于50的韩剧数量:', star5_rate_moreThan50)
# 打印信息:
五星好评率大于50的韩剧数据: 29
star5_rate_bins = np.arange(0, 100, 10)
pie_data['star5_rate_cut'] = pd.cut(pie_data['star5_rate'], star5_rate_bins)
pie_data['star5_rate_cut'] = pie_data['star5_rate_cut'].astype('str')
star5_rate_label = pie_data['star5_rate_cut'].value_counts().index.tolist()
star5_rate_counter = pie_data['star5_rate_cut'].value_counts().values.tolist()
plt.figure(figsize=(10,10))
plt.pie(star5_rate_counter, labels=star5_rate_label, autopct='%1.1f%%')
plt.savefig('/Users/mac/Desktop/五星好评率分布.jpg')

# 五分好评率前十的韩剧,有时候评分不太靠谱,五分好评率是个不错的参考指标。
df_sortByScores[['star5_rate', 'names']].sort_values(['star5_rate'], ascending=False)[:10]

演员情况分析
# 拿出前100部韩剧出演的演员。
actors_list = []
for item in df_sortByScores['actors']:
item = item.replace('[', '').replace(']', '').replace('\'', '').replace('\'', '').split(',')
actors_list.extend(item)
# print(actors_list)
# 统计演员参演次数。
actors_word_counts = collections.Counter(actors_list)
actors_count_df = pd.DataFrame({'actors_names': list(actors_word_counts.keys()),
'actors_times': list(actors_word_counts.values())})
# 筛选出参演次数大于等于5的演员,发现前面的大都是老戏骨,现在比较热门稍微往后靠。
actors_df_bigger_than_5 = actors_count_df[actors_count_df['actors_times'] >= 5].sort_values(['actors_times'], ascending=False)
actors_df_bigger_than_5
# 打印信息:
actors_names actors_times
190 金元海 11
192 李俊赫 9
33 孙荣顺 9
420 金美京 9
225 严孝燮 9
134 成东日 8
352 利旻 8
49 刘在明 8
730 吴义植 7
345 李彩京 7
284 全振序 7
118 李圭燮 7
235 朴健洛 7
228 崔镇浩 7
585 金光奎 7
221 崔秉默 7
372 赵在允 6
226 尹敬浩 6
216 李成俊 6
726 李钟硕 6
5 金善映 6
186 孙钟学 6
651 安内相 6
180 尹仲勋 6
571 徐光载 6
165 丁文晟 6
741 南基爱 6
752 罗映姫 5
398 尹柱万 5
353 金旻奎 5
659 刘仁娜 5
378 金炳哲 5
380 金惠恩 5
388 金智媛 5
838 姜其永 5
765 南柱赫 5
405 申秀妍 5
614 丹尼尔·乔伊·奥尔布赖特 5
514 吴雅琳 5
551 徐正妍 5
484 朴元尚 5
492 郑栋焕 5
496 张文硕 5
513 高圭弼 5
485 李伊庚 5
250 张铉诚 5
340 李宥俊 5
313 南多凛 5
39 丁海寅 5
47 李振权 5
50 禹贤 5
76 李光洙 5
81 金學善 5
95 高甫洁 5
105 全国焕 5
115 黃相庆 5
126 郑秀晶 5
147 张赫镇 5
175 姜河那 5
179 李璟荣 5
188 吴闵硕 5
194 金正洙 5
201 丁世亨 5
202 孟奉鶴 5
208 崔英 5
214 黄锡晶 5
234 张成范 5
240 李豪宰 5
242 权赫洙 5
251 李时言 5
261 南文哲 5
288 金姬贞 5
292 金贤彬 5
939 李必模 5
重点来啦!!!
# 看下我二硕和朴宝拉的出现情况,二硕严重推荐《听见你的声音》和《当你沉睡时》,朴宝英严重推荐《噢我的鬼神大人》和《大力女都丰顺》。
print('前100韩剧中李钟硕出现次数:', actors_word_counts.get('李钟硕'))
print('前100韩剧中朴宝英出现次数:', actors_word_counts.get('朴宝英'))
# 打印信息:
前100韩剧中李钟硕出现次数: 6
前100韩剧中朴宝英出现次数: 2
# 李钟硕出演的韩剧。
df_sortByScores[df_sortByScores.actors.str.contains('李钟硕')][['names', 'scores']].sort_values(['scores'], ascending=False)

# 朴宝英出演的韩剧。
df_sortByScores[df_sortByScores.actors.str.contains('朴宝英')][['names', 'scores']].sort_values(['scores'], ascending=False)

最后看看导演
# 拿出前100部韩剧的导演。
directors_list = []
for item in df_sortByScores['directors']:
item = item.replace('[', '').replace(']', '').replace('\'', '').replace('\'', '').split(',')
directors_list.extend(item)
# print(directors_list)
directors_word_counts = collections.Counter(directors_list)
director_df = pd.DataFrame({'directors_names': list(directors_word_counts.keys()),
'directors_scores': list(directors_word_counts.values())})
# 无导演的是动画片,可忽略。
director_df.sort_values(['directors_scores'], ascending=False)
# 打印信息:
directors_names directors_scores
9 8
0 申源浩 4
10 李应福 4
14 金炳洙 4
50 朴信宇 3
1 金秉旭 3
5 金元锡 3
35 朴俊和 3
7 金奎泰 3
33 陈赫 3
15 李政孝 2
40 宋贤旭 2
57 金洪善 2
59 全基尚 2
19 安畔锡 2
22 李亨民 2
13 李胜英 2
3 金昌东 2
4 洪忠灿 2
12 金英基 2
6 安吉镐 2
67 朴洪均 1
54 尹成植 1
47 朴秀真 1
48 申承佑 1
70 姜信孝 1
49 池英洙 1
51 柳济元 1
52 李炳勋 1
69 朱东民 1
53 郑大允 1
55 金道勋 1
66 咸俊浩 1
56 李明佑 1
68 金成旭 1
58 李容硕 1
60 洪成昌 1
61 毛完日 1
62 表民洙 1
45 金政民 1
63 尹成浩 1
64 表民洙 1
65 崔成范 1
46 吴庆焕 1
36 金尹哲 1
44 张正道 1
26 金镇元 1
2 李英哲 1
8 申景秀 1
11 河炳勋 1
16 金镇满 1
17 金大镇 1
18 崔哉玧 1
20 赵贤卓 1
21 李太坤 1
23 刘仁值 1
24 李昌民 1
25 朴秀真 1
27 崔正奎 1
43 金希元 1
28 金锡允 1
29 赵秀沅 1
30 申承佑 1
31 李政燮 1
32 金振宇 1
34 吴贤钟 1
37 张太维 1
38 申宇哲 1
39 金尚昊 1
41 权锡章 1
42 李娜静 1
71 富圣哲 1
没错,这篇其实根本不是什么技术分析文章,只是一篇二硕和朴宝英脑残粉的软文。