@Author:By Runsen
@Date: 2020/5/8
1、前言
最近需要爬取当当关于医学的图书,做一个数据分析,别问我为什么做,是为了Money。
2、 爬虫
2.1 分析网页
爬取的信息都在一个li的标签中,通过xpath进行解析得到需要爬取的内容
然后在分析换页的url存在什么的变化。第一页的url:http://search.dangdang.com/?key=%D2%BD%D1%A7&category_path=01.49.01.20.00.00
。第二页的url:http://search.dangdang.com/?key=%D2%BD%D1%A7&category_path=01.49.01.20.00.00&page_index=2
,多了一个page_index参数
2.2 保存
直接保存csv格式,每解析一个li就直接写进去,不需要导入什么csv模块,直接with open简单费事。
2.3 爬虫代码
爬虫代码只要注意解析正确就可以了,因为得到的是一个列表,取一个[0]就OK了,如果遇到了一些无关的信息,直接干脆replace,只要解析正确就基本很问题,有些在网页上没有爬取的信息,比如出版时间,就来一个判断就OK了,,代码如下。
'''
@Author: Runsen
@微信公众号: 润森笔记
@博客: https://blog.csdn.net/weixin_44510615
@Date: 2020/4/30
'''
import requests
from lxml import etree
headers = {"Cookie": "__permanent_id=20200317115740144182857158771910961; __ddc_15d_f=1587108095%7C!%7C_utm_brand_id%3D11106; producthistoryid=24183591%2C25066760%2C25107201%2C25859443%2C25199640%2C23254747%2C1621922974%2C1598857528; from=460-5-biaoti; order_follow_source=P-460-5-bi%7C%231%7C%23www.baidu.com%252Fother.php%253Fsc.000000j_MQZMhq-20ZeR4F-J1G-WoC-SeGT99aHZUDfXtGNG0reHnKFGSRElMNxKBnZFv6Xqv%7C%230-%7C-; ddscreen=2; __visit_id=20200430095740321273567927431228714; __out_refer=1588211860%7C!%7Cwww.baidu.com%7C!%7C; __ddc_1d=1588211860%7C!%7C_utm_brand_id%3D11106; __ddc_24h=1588211860%7C!%7C_utm_brand_id%3D11106; __ddc_15d=1588211860%7C!%7C_utm_brand_id%3D11106; MDD_channelId=70000; MDD_fromPlatform=307; dest_area=country_id%3D9000%26province_id%3D111%26city_id%3D0%26district_id%3D0%26town_id%3D0; pos_1_end=1588212673074; pos_1_start=1588212673842; search_passback=4d6eacd80001ddc2533baa5efc010000; __trace_id=20200430104334510169097706062414837; pos_9_end=1588214620278; pos_0_start=1588214620306; pos_0_end=1588214620313; ad_ids=2608809%2C3437571%2C2797900%2C2797887%2C2797886%2C2797866%2C2797864%2C2797860%2C3425424%2C2608826%7C%233%2C3%2C3%2C3%2C4%2C4%2C3%2C2%2C2%2C1; __rpm=s_112100.155956512835%2C155956512836..1588214610437%7Cs_112100.155956512835%2C155956512836..1588214628519","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36"}
with open('data.csv', 'a+') as f:
f.write('书籍名称' + ',' + '出版时间' + ',' + '出版社' + ',' + '图书价格'+ ',' + '评论'+ '\n')
for i in range(1,101):
url="http://search.dangdang.com/?key=%D2%BD%D1%A7&category_path=01.49.01.20.00.00&page_index={}".format(i)
res = requests.get(url,headers=headers)
res.encoding ='gbk'
tree = etree.HTML(res.text)
for li in tree.xpath("//ul[@id='component_59']")[0]:
title = li.xpath("./a/@title")[0].replace(",",'')
if li.xpath(".//p[@class='search_book_author']/span[2]/text()"):
time = li.xpath(".//p[@class='search_book_author']/span[2]/text()")[0].replace("/","").replace(",",'')
else:
time = ''
if li.xpath(".//a[@name='P_cbs']"):
press = li.xpath(".//a[@name='P_cbs']/text()")[0]
else:
press = ''
price = li.xpath(".//span[@class='search_now_price']/text()")[0][1:]
comment= li.xpath(".//a[@name='itemlist-review']/text()")[0].replace("条评论","")
print(title,time,press,price,comment)
f.write(title+','+ time+','+press+','+price+','+comment+'\n')
执行上面的代码,得到的数据如下图所示。
爬了一共6000本医学图书,学医的你们要学6000本图书,才有可能成为我心目中的钟老的人物。
3、数据分析
爬取数据为了干嘛,就是分析下,装个小逼。
3.1 数据预处理
爬取的数据存在空值,直接dropna就ok了,然后发现csv都是文本格式,直接astype就OK了。
data = pd.read_csv("data.csv",encoding='gbk')
data.dropna(inplace=True)
data['图书价格'].astype(np.float)
data['评论'].astype(np.int)
3.2 词云
下面通过书籍名称制作一个词云图,直接将所有的标题合并成一个长文本,再用jieba分词,都是小儿科的东西。
def wordCloud_title(data):
row_titles = data['书籍名称']
row_title_list = []
for row_t in row_titles:
row_title_list.append(row_t)
row_title_str = "".join(row_title_list) # 列表变成字符串
data = ' '.join(jieba.cut(row_title_str))
my_word_cloud = WordCloud(
font_path='C:\Windows\Fonts\simkai.ttf',
background_color='white',
scale=8
)
myWordCloud = my_word_cloud.generate(data)
myWordCloud.to_file('title_keyword.jpg')
最后制作的词云图就是这样的,都是一些学习教材。
3.3 价格分布
因为爬取有价格信息,那直接做一个医术的价格分布图,用pyechart算了,不用matplotlib,为什么,看起来高大厦点,逼也要装的好些。
def price_map(data):
df_price=data['图书价格']
category=[0,20,30,50,80,100,150,200,500,16000]
price_range=pd.cut(df_price,category)
#counts=len(price_range)#这是一个列表
#print(counts)
#print(price_range)
Count=Counter(price_range)
price=[]#导入列表之后格式不对
num=[]
for key, value in Count.items():
price.append(key)
num.append(value)
prices=[]#另建一个
for i in price:
i=str(i)
i=i[i.find('('):i.find('c')]
i=i.replace('(','')
i='价格区间('+i+')'
prices.append(i)
c = (
Pie()
.add("", [list(z) for z in zip(prices,num )]
,center=["35%", "60%"]
)
.set_global_opts(title_opts=opts.TitleOpts(title="价格区间")
,legend_opts=opts.LegendOpts(pos_left="75%"),
)
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
)
c.render(path='price_range.html')
最后制作的价格分布饼图就是这样子的
现在的医书都是在100块以下的,没什么有分析的。
3.4 图书出版最多10个的出版社
任何图书都有出版出名的出版社,我不知道医学这方面最出名的出版社是谁,那就绘制一个出版最多10个的出版社的玫瑰图。
代码都是抄官网的,改改数据源就OK了。
def plot_press(data):
# 图书出版最多10个的出版社
df_press=data['出版社']
Count = list(Counter(df_press).most_common(10))
pie = (
Pie()
.add(
'出版社数量玫瑰图',
[list(z) for z in Count],
radius=['50%', '100%'], # 设置内径外径
# rosetype='radius' 圆心角展现数据百分比,半径展现数据大小
# rosetype='area' 圆心角相同,为通过半径展现数据大小
rosetype='radius',
label_opts=opts.LabelOpts(is_show=True)
)
.set_global_opts(title_opts=opts.TitleOpts(title='出版社玫瑰图'),
legend_opts=opts.LegendOpts(is_show=False))
)
pie.render('出版社玫瑰图.html')
最后制作的最多10个的出版社玫瑰图就是这样子的
人民卫生出版社怎么这么牛逼,竟然出版了2025本,我也爬取了6000个数据,三分之一的医学书都是人民卫生出版社出版的。
3.5 图书评论最多5个出版社
还有一个图书评论的数据没有用到,咱们分析一波。。
我们就绘制一个柱状图吧,把图书评论最多5的出版社绘制出来
def plot_comment(data):
# 图书评论最多10个的出版社
df = data.sort_values(by='评论',ascending=False)
names = list(df['书籍名称'][:5].values)
nums = []
for i in range(5):
nums.append(int(df.iloc[i,-1]))
print(nums)
grid = Grid()
bar = (
Bar()
.add_xaxis(names)
.add_yaxis("评论数量",nums)
.set_colors(['#00A383'])
.set_global_opts(xaxis_opts=opts.AxisOpts(name_rotate=60, name="书籍名称", axislabel_opts={"rotate": 45}))
.set_global_opts(yaxis_opts=opts.AxisOpts( name="评论数量"))
)
grid.add(bar,grid_opts=opts.GridOpts(pos_bottom="45%"))
grid.render("评论最多书籍.html")
绘制的柱状图如下图所示
妈呀,竟然有82252的评论,什么书,这么牛逼,82252的评论,销量都是几百万的,也就是我国几百万医生护士都需要学习的书
原来这是教材,还前2年出版,竟然达到了几百万的销量,而且还只是在当当,跟高等数学有的一比。
3.6 医书出版趋势图
我记得有一个出版时间,那就分析下每年的出版趋势图
def plot_time(data):
data.dropna(inplace=True)
data['图书价格'].astype(np.float)
data['评论'].astype(np.int)
data['出版时间'] = pd.to_datetime(data['出版时间'])
data['Year'] = data['出版时间'].map(lambda x: x.year)
data['Month'] = data['出版时间'].map(lambda x: x.month)
print(data.head())
data.groupby(['Year', 'Month'])['出版社'].count().plot()
plt.xlabel('年月',)
plt.ylabel('出版社出书数量')
plt.show()
data.groupby(['Year'])['出版社'].count().plot()
plt.xlabel('年份')
plt.ylabel('出版社出书数量')
plt.show()
绘制的医书出版趋势图(以年为单位)
绘制的医书出版趋势图(以年月为单位)
4、致敬医务人员
最后,当然要致敬医务人员。2020年,因新冠肺炎疫情的暴发,我们的国家和人民迎来了这场史无前例的危机与挑战,你们为战胜疫情,为保护国家安全、社会稳定、人民健康,全国各地医务人员纷纷挺身而出,奋战一线,舍小家为大家,成为最美逆行者。
向奋战在抗击疫情前线的所有医务人员致敬!向男神钟南山致敬!以后叫后代不要干IT互联网的,做一个医生有面子,光荣!
链接:https://pan.baidu.com/s/1XIEPfuubdO7uSP9HNpQRFA
提取码:d30z
转载:https://blog.csdn.net/weixin_44510615/article/details/105992182