网页抓取数据百度百科(Python爬取《权力的游戏第八季》演员数据并分析数据爬取)
优采云 发布时间: 2021-12-05 18:07网页抓取数据百度百科(Python爬取《权力的游戏第八季》演员数据并分析数据爬取)
Python爬取分析《权力的游戏第8季》演员数据
数据爬取一、 浏览需要爬取的网页
首先浏览要爬取的网页,也就是百度百科的“权力的游戏第八季”页面,发现演员表里有每个演员条目的链接。在这里你可以通过爬取获取每个演员的入口链接,方便你。爬取了每个actor的详细信息:
然后进入龙母的入口页面:
在这里找到它的基本信息:
因此,我们可以将之前爬取得到的各个actor的入口链接进行爬取,然后爬取并保存各个actor的基本信息,方便后续的数据分析。
二、 在百度百科中爬取《权力的游戏》第八季的演员阵容,获取各个演员的链接并存入文件
import re
import requests
import json
import pandas
import os
import sys
from bs4 import BeautifulSoup
#获取请求
def getHTMLText(url,kv):
try:
r = requests.get(url, headers=kv)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except Exception as e:
print(e)
#解析出演员姓名与链接数据并存入文件
def parserData(text):
soup = BeautifulSoup(text,'lxml')
review_list = soup.find_all('li',{'class':'pages'})
soup1 = BeautifulSoup(str(review_list),'lxml')
all_dts = soup1.find_all('dt')
stars = []
for dt in all_dts:
star = {}
star["name"] = dt.find('a').text
star["link"] = 'https://baike.baidu.com' + dt.find('a').get('href')
stars.append(star)
json_data = json.loads(str(stars).replace("\'","\""))
with open('work/'+'stars.json','w',encoding='UTF-8') as f:
json.dump(json_data,f,ensure_ascii=False)
三、 爬取演员的详细信息并保存在文件中(每个演员的图片也下载保存)
#爬取并解析出演员详细信息与图片并存入文件
def crawl_everyone(kv):
with open('work/' + 'stars.json', 'r', encoding='UTF-8') as file:
json_array = json.loads(file.read())
star_infos = []
for star in json_array:
star_info = {}
name = star['name']
link = star['link']
star_info['name'] = name
#向选手个人百度百科发送一个http get请求
r = requests.get(link,headers=kv)
soup = BeautifulSoup(r.text,'lxml')
#获取选手的国籍、星座、身高、出生日期等信息
base_info_div = soup.find('div',{'class':'basic-info cmn-clearfix'})
dls = base_info_div.find_all('dl')
for dl in dls:
dts = dl.find_all('dt')
for dt in dts:
if "".join(str(dt.text).split()) == '国籍':
star_info['nation'] =''.join(str(dt.find_next('dd').text).split()).replace("\n","").replace("[1]","")
if "".join(str(dt.text).split()) == '星座':
con_str=str(dt.find_next('dd').text).replace("\n","")
if '座' in con_str:
star_info['constellation'] = con_str[0:con_str.rfind('座')]
if "".join(str(dt.text).split()) == '身高':
if name=='约翰·C·布莱德利':
star_info['height'] ='173'
else:
height_str = str(dt.find_next('dd').text)
star_info['height'] =''.join(str(height_str[0:height_str.rfind('cm')]).split()).replace("\n","").replace("[2]","") .replace("[4]","")
if "".join(str(dt.text).split()) == '出生日期':
birth_day_str = str(dt.find_next('dd').text).replace("\n","")
if '年' in birth_day_str:
star_info['birth_day'] = birth_day_str[0:birth_day_str.rfind('年')]
star_infos.append(star_info)
#从个人百度百科页面中解析得到一个链接,该链接指向选手图片列表页面
if soup.select('.summary-pic a'):
pic_list_url = soup.select('.summary-pic a')[0].get('href')
pic_list_url = 'https://baike.baidu.com' + pic_list_url
#向选手图片列表页面发送http get请求
pic_list_response = requests.get(pic_list_url,headers=kv)
#对选手图片列表页面进行解析,获取所有图片链接
soup1 = BeautifulSoup(pic_list_response.text,'lxml')
pic_list_html=soup1.select('.pic-list img ')
pic_urls = []
for pic_html in pic_list_html:
pic_url = pic_html.get('src')
pic_urls.append(pic_url)
#根据图片链接列表pic_urls, 下载所有图片,保存在以name命名的文件夹中
down_save_pic(name,pic_urls)
#将个人信息存储到json文件中
#print("%s",name)
json_data = json.loads(str(star_infos).replace("\'","\""))
with open('work/' + 'stars_info.json', 'w', encoding='UTF-8') as f:
json.dump(json_data, f, ensure_ascii=False)
print('所有信息与图片爬取完成')
def down_save_pic(name,pic_urls):
#根据图片链接列表pic_urls, 下载所有图片,保存在以name命名的文件夹中,
path = 'work/'+'pics/'+name+'/'
if not os.path.exists(path):
os.makedirs(path)
for i, pic_url in enumerate(pic_urls):
try:
pic = requests.get(pic_url, timeout=15)
string = str(i + 1) + '.jpg'
with open(path+string, 'wb') as f:
f.write(pic.content)
#print('成功下载第%s张图片: %s' % (str(i + 1), str(pic_url)))
except Exception as e:
print('下载第%s张图片时失败: %s' % (str(i + 1), str(pic_url)))
print(e)
continue
# 调用函数爬取信息
kv={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/67.0.3396.99 Safari/537.36' }
url = 'https://baike.baidu.com/item/%E6%9D%83%E5%8A%9B%E7%9A%84%E6%B8%B8%E6%88%8F%E7%AC%AC%E5%85%AB%E5%AD%A3'
html = getHTMLText(url,kv)
parserData(html)
crawl_everyone(kv)
四、 爬取结果:
1.保存的演员链接文件:
2.保存的演员信息文件:
3.下载保存的演员图片:
数据分析一、生成演员年龄分布直方图
import numpy as np
import json
import pandas as pd
import matplotlib.font_manager as font_manager
#显示matplotlib生成的图形
%matplotlib inline
df=pd.read_json('work/stars_info.json',dtype={'birth_day' : str})
grouped=df['name'].groupby(df['birth_day'])
s=grouped.count()
zone_list=s.index
count_list=s.values
#设置显示中文
plt.rcParams['font.sans-serif']=['SimHei']#指定默认字体
plt.figure(figsize=(20,15))
plt.bar(range(len(count_list)),count_list,color='r',tick_label=zone_list,facecolor='#FFC0CB',edgecolor='white')
#调节横坐标的倾斜度,rotation是读书,以及设置刻度字体大小
plt.xticks(rotation=45,fontsize=20)
plt.yticks(fontsize=20)
plt.legend()
plt.title('''《权力的游戏第八季》演员年龄分布图''',fontsize=24)
plt.savefig('work/result/birth_result.jpg')
plt.show()
二、 生成演员国籍分布饼图
import matplotlib.pyplot as plt
import numpy as np
import json
import matplotlib.font_manager as font_manager
with open('work/stars_info.json', 'r', encoding='UTF-8') as file:
json_array = json.loads(file.read())
#设置显示中文
plt.rcParams['font.sans-serif']=['SimHei']#指定默认字体
#绘制选手身高分布饼状图
nations = []
counts = []
for star in json_array:
if 'nation' in dict(star).keys():
nation = star['nation']
nations.append(nation)
print(nations)
nation_list = []
count_list = []
n1 = 0
n2 = 0
n3 = 0
n4 = 0
for nation in nations:
if nation == '英国':
n1 += 1
elif nation == '美国':
n2 += 1
elif nation == '丹麦':
n3 += 1
else:
n4 += 1
labels = '英国', '美国', '丹麦', '其它'
nas = [n1, n2, n3, n4]
explode = (0.2, 0.1, 0, 0)
fig1, ax1 = plt.subplots()
ax1.pie(nas, explode=explode, labels=labels, autopct='%1.1f%%',
shadow=True)
ax1.axis('equal')
plt.savefig('work/result/nation_result.jpg')
plt.title('''《权力的游戏第八季》演员国籍分布图''',fontsize = 14)
plt.show()
三、生成演员身高分布饼图
<p>import matplotlib.pyplot as plt
import numpy as np
import json
import matplotlib.font_manager as font_manager
with open('work/stars_info.json', 'r', encoding='UTF-8') as file:
json_array = json.loads(file.read())
#设置显示中文
plt.rcParams['font.sans-serif']=['SimHei']#指定默认字体
#绘制选手身高分布饼状图
heights = []
counts = []
for star in json_array:
if 'height' in dict(star).keys():
height = float(star['height'][0:3])
heights.append(height)
print(heights)
size_list = []
count_list = []
size1 = 0
size2 = 0
size3 = 0
size4 = 0
for height in heights:
if height