网址
http://www.hurtrecord.com/bgm/theme.html
分析
每个主题下面有很多小类
网站样式
点开小类是下载链接:
小类里面的音乐,下载箭头背后就是链接
怎样把小类归类?
小类在主题下面,但是获取小类的时候又不能直接获取主题,因为二者样式不一样, 这里我推荐把网页的源代码字符串化,然后小类的样式和主题位置的样式也字符串化,这样使用字符串中的index方法就可以获取在网页中的相对位置了,最起码做个比较是没有问题的。可以得到数据帧。需要的帧形式:主题,小类,小类链接。
怎样把小类下面的音乐拿出来并且和小类关联?
现在要根据小类的链接去打开页面挖掘歌曲,要返回歌曲名称和下砸地址的列表。
这里我是每次打来小类页面生成列表时候,转化成pandas的数据帧对象,然后统一添加小类的名称。构建列表:小类名,歌名,歌名链接
用merge方法合并主键和外键。
pd.merge(catalog_df, song_df, on='小类') 笛卡尔积,当两个表连接时,有相同的key值就产生积。
代码
#爬取这个日本音乐网站的所有下载直链
import requests,os
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
music_path = './music_link_output' #输出的文件夹
if not os.path.exists(music_path):
os.makedirs(music_path)
url = 'http://www.hurtrecord.com/bgm/theme.html' #一个日本网站的音乐
def get_url(url):
music_list = []
theme_list = []
web_data = requests.get(url)
soup = BeautifulSoup(web_data.content.decode('utf-8'), 'lxml')
strsoup = str(soup)
for theme in soup.select('#cont > h2.sube'):
theme_txt = theme.text
if '/' in theme_txt:
theme_txt = ''.join(theme_txt.split('/'))
theme_pos = strsoup.index(str(theme))
theme_list.append([''.join(theme_txt.split()),theme_pos]) #主题,大类位置
print(theme_list)
items = soup.select('#cont > div > a')
for item in items:
item_txt = str(item)
if 'border' not in item_txt:
title = str(item).split('▷ ')[1].split('</a')[0]
href = item['href']
item_pos = strsoup.index(str(item))
music_list.append([title,item_pos,href]) #小类名、小类位置、小类链接
return theme_list, music_list
#需要的帧形式: 大类,小类,小类链接
def get_music_link(url):
# 样式 #table-010 > tbody > tr > td:nth-child(5) > a
url = 'http://www.hurtrecord.com/bgm/84/'
web_data = requests.get(url)
soup = BeautifulSoup(web_data.content.decode('utf-8'), 'lxml')
music_link_list = []
for item in soup.select('#table-010 > tbody > tr'): # 使用p:nth-of-type(这里写子的序数)也可以
if '<th>No.</th>' not in str(item):
music_link_list.append(
[list(item)[1].text, str(list(item)[4]).split('<td><a href="')[1].split('" onclick')[0]]
)
return music_link_list
theme_list, music_list = get_url(url)
theme_list = [[each_theme[0] for each_theme in theme_list],[each_theme[1] for each_theme in theme_list]]
catalog = {'小类': [each_cata[0] for each_cata in music_list],
'小类位置': [each_cata[1] for each_cata in music_list],
'小类链接': [each_cata[2] for each_cata in music_list]}
catalog_df = pd.DataFrame(catalog)
catalog_df.insert(0,'主题',pd.cut(catalog['小类位置'],bins = theme_list[1] + [np.inf],labels = theme_list[0]))
for my_index in catalog_df.index: #每一行 有主题,小类,小类的链接。现在要根据小类的链接去搜索歌曲,要返回歌曲
this_catalog = catalog_df.loc[my_index]
this_catalog_name = this_catalog['小类']
print(f"正在抓取{this_catalog['主题']}中的{this_catalog_name}")
songs = get_music_link(this_catalog['小类链接']) #列表,元素是歌名+链接
#构建列表:小类名,歌名,歌名链接
this_songs_df = pd.DataFrame({'小类':[this_catalog_name]*len(songs),
'曲名': [song[0] for song in songs],
'下载地址':[song[1] for song in songs]
})
song_df = this_songs_df if my_index == 0 else pd.concat([song_df,this_songs_df])
data = pd.merge(catalog_df, song_df, on='小类') #笛卡尔积,当两个表连接时,有相同的key值就产生积。
data.drop(['小类链接','小类位置'], inplace=True)
data.to_csv(os.path.join(music_path,'Japanese_Music.csv'), index = False) #其实默认是带索引保存的,这里不该带索引。
data = pd.read_csv('/Users/miraco/PycharmProjects/grabnet/music_link_output/Japanese_Music.csv')
x = [0]
#data.drop(data.columns[x], axis=1, inplace=True) #其实删除第0列,索引列,如果当初选择了带索引保存
count_df = data.groupby('主题').count()['曲名']
count_df.plot(kind = 'bar',stacked = True)
plt.title(u'歌曲统计', fontsize=18, fontproperties=FontProperties(fname='/System/Library/Fonts/PingFang.ttc'))
plt.xticks(fontproperties=FontProperties(fname='/System/Library/Fonts/PingFang.ttc'),rotation =30)
plt.yticks(fontproperties=FontProperties(fname='/System/Library/Fonts/PingFang.ttc'))
plt.xlabel('主题',fontproperties=FontProperties(fname='/System/Library/Fonts/PingFang.ttc'))
plt.ylabel('曲数目',fontproperties=FontProperties(fname='/System/Library/Fonts/PingFang.ttc'))
#plt.legend(prop = FontProperties(fname='/System/Library/Fonts/PingFang.ttc'))
plt.tight_layout()
plt.show()
运行结果:
统计
表格
表格
其实如果想要下载的话也是可以的:
但是我没什么精力去弄这个了,举个例子。
import requests
url = 'http://www.hurtrecord.com/bgm/67/shizukesa-no-ato.mp3'
music = requests.get(url)
with open('music.mp3','wb') as f:
f.write(music.content)
踩过的坑
-
有兴趣可以试试重命名练练手
https://www.cnblogs.com/jmlovepython/p/5670207.html -
文件下载Q&A
https://blog.csdn.net/sinat_36246371/article/details/62426444 -
数据帧的行列操作
https://blog.csdn.net/claroja/article/details/65661826
https://www.jianshu.com/p/67e67c7034f6
诸如:列删除
import pandas as pd
import numpy as np
df = pd.DataFrame(np.arange(12).reshape(3,4),
columns=['A', 'B', 'C', 'D'])
x=[1,2]
df.drop(df.columns[x], axis=1, inplace=True)
print df














网友评论