使用selenium获取网易云指定歌曲评论
最近一段时间在学习python爬虫,结合自己学习的内容写一个简单爬虫来获取网易云音乐中指定歌曲的评论信息。第一次发博客并且也是入门爬虫不久,有问题的地方希望大家指出,共同进步~~!
我们的目标是爬取网易云中想要的任何一首歌曲的评论。
观察网易云音乐的网页可以发现两个特点:
- 网页是js动态加载的
- 使用了iframe框架
所以在本文使用Selenium结合Chrome来爬取内容( PhatomJS已经被建议不使用了,使用chrome的无头模式)
首先打开网易云音乐
接下来要查找搜索框的元素
看到input的name是‘srch’,同时这部分代码还不在iframe框架内,所以这里可以直接获取该元素。
chrome_options = Options()
self.chrome_options.add_argument('--headless')
self.chrome_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(chrome_options = self.chrome_options)
#driver = webdriver.Chrome()
driver.get(self.url)
time.sleep(0.5)
driver.set_window_size(1280,800)
put = driver.find_element_by_id("srch")
在这里遇到了一个bug卡了我好久?,就是当设置为无头chrome时打开浏览器的当前界面是没有这个元素的,需要将它显示出来才可以进行下一步操作,而我把窗口放到最大或是移动滚动条都没有效果,后来把屏幕放大到指定数值才可以继续操作。
在操作过程中的把页面截取下来才看出问题。
driver.save_screenshot('D:\\a.png')
接下来是在搜索框中输入搜索内容进入下一个页面
put.send_keys('云烟成雨') #一首我特别喜欢的民谣
time.sleep(0.5)
put.send_keys(Keys.ENTER) #回车操作
到了这个界面后因为我遇到有的歌曲搜索后是直接显示在了专辑栏,所以我先点击单曲栏,再选中第一首歌。
需要注意的是这里已经进入了iframe包括的代码内容,所以需要先把iframe框架中的内容加载出来:
driver.switch_to_frame(‘g_iframe’)
这里的’g_iframe’是iframe的框架。
wait = WebDriverWait(driver,10)
wait.until(EC.presence_of_element_located((By.ID,'g_iframe')))
driver.switch_to_frame('g_iframe') #网页使用了iframe,需要进行读取
time.sleep(1)
put = driver.find_element_by_class_name('fst') #选中单曲列表
put.click()
wait = WebDriverWait(driver,10)
wait.until(EC.presence_of_element_located((By.CLASS_NAME,'w0')))
music = driver.find_element_by_class_name('w0')
music = music.find_element_by_class_name('text')
music = music.find_element_by_class_name('s-fc7')
music_lyrics = driver.find_element_by_class_name('w1').text
music_name = driver.find_element_by_class_name('w0').text
print('您搜索到的音乐是 '+music_name+' '+music_lyrics) #看一下自己到底搜到的是什么歌
music.click()
接下来就是开始获取每一页上的评论信息,从每一条评论中可以得到的信息是评论者的姓名,评论的内容,评论的时间和点赞数,还有是针对另一个评论者的回复。这里建一个people的字典来存储这些信息。
people = {
'names':[], 'comments':[], 'dates':[], 'votes':[], 'replied_names':[], 'replied_comments':[]}
在获取信息时通过一页页地向后翻来加载评论信息。
def download_next_page(driver):
'获取下一页的html代码'
time.sleep(0.5)
next_page = driver.find_element_by_class_name('znxt')
time.sleep(0.5)
driver.execute_script("window.scrollTo(0,document.body.scrollHeight)") #把滚动条拉到翻页按钮处模仿用户操作
next_page.click()
wait = WebDriverWait(driver,10)
wait.until(EC.presence_of_element_located((By.CLASS_NAME,'itm'))) #这里是等到确保页面加载完成再进行下一步操作
content = driver.page_source
content = content.replace('<br />','\n') #输出时按照网页上的格式换行保存评论内容
html = BeautifulSoup(content,'lxml')
return html
也可以向前翻页
def download_previous_page(driver):
'获取上一页的HTML代码'
time.sleep(1)
previous_page = driver.find_element_by_class_name('zprv')
previous_page.click()
#因为向前翻页的时候页面都已经加载过了所以不需要再把滚动条拉下来
wait = WebDriverWait(driver,10)
wait.until(EC.presence_of_element_located((By.CLASS_NAME,'itm')))
content = driver.page_source
content = content.replace('<br />','\n')
html = BeautifulSoup(content,'lxml')
return html
在获取评论信息的时候首先还是需要将数据信息规范成统一形式的,研究后使用两个函数来统一时间和点赞数的格式。
def change_vote(vote):
'确保评论的点赞数格式统一为int'
try:
change = vote[vote.index('(')+1:vote.index(')')]
if '万' in change:
change = int(float(change[:change.index('万')])*10000)
else:
change = int(change)
except