selenium这是一个第三方库我们可以通过 pip install selenium
来安装这个第三方库。
Selenium 是一个 Web 的自动化测试工具,最初是为网站自动化测试而开发的,就像玩游戏用的按键精灵,可以按指定的命令自动操作。Selenium 测试工具直接操控浏览器中,就像真正的用户在操作一样。Selenium 可以根据的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生等。
Selenium 支持多种浏览器,最常见的就是 火狐 和 谷歌 浏览器。首先在电脑上下载浏览器,浏览器版本不宜过新。这里我用的是更新过的Microsoft.Edge
Microsoft.Edge 驱动链接地址
Chrome驱动链接地址
FireFox驱动链接地址
下载后我们可以把它放在python的同级目录(调用时不用再写路径),也可以不放,这里我选择不放。
好!这里我们直接开干!
from selenium import webdriver # 导入模块
url = 'https://music.163.com/#/song?id=86369' # 爬取歌曲评论的链接
class CloudMusic:
def __init__(self, url):
self.url = url
self.driver = webdriver.Edge(executable_path="./msedgedriver.exe") # 创建驱动器
def get_content(self):
self.driver.get(url) # 请求网页
if __name__ == '__main__':
spider = CloudMusic(url)
spider.get_content()
这里我们先定义一个类对然后定义了属性,请求的网页链接,以及驱动器的创建,这里需要注意的是,因为selenium是直接操控浏览器,所以我们只有运行后才能看到结果。
这里运行后我们看到它创建了浏览器并且访问了页面,和我们正常的页面还是有区别的对吧。
这里我们需要注意的是如果我们跳过ifram标签直接解析或者访问我们需要的元素我们是访问不到的,因为< frame> 标签,浏览器会在标签中打开一个特定的页面窗口(框架),它在本窗口中嵌套进入一个网页,就像登录时候他会弹出登录对话框,这时候对话框后面的内容我们是无法访问或者操作的,所以我们要进去ifram框中才能取得元素。
通过find查找我们发现网页中有6个和ifram相关的元素,三个同级还有三个没有啥内容,所以判断我们需要的页面元素在第一个框
def get_content(self):
self.driver.get(url) # 请求网页
self.driver.switch_to.frame(0) # 0代表进入第一个框 索引
然后我们就可以来选择我们需要的元素了。selenium给我们提供了很多提取页面元素的方法(后续会写一篇selenium的快速用法),这里我们选择css选择器,我觉得比较简单,而且也可以在网页上直接定位到内容。
这样我们就定位到了选择的标签,接下来我们试着来提取标签内容
从截图中我们看到我们已经提取到了内容,但是看不太懂对吧,其实这是因为我们没有转换格式,通过type(common)
我们知道他其实是(
网页元素我们可以用.text
变成我们可以看懂的文本模式。
这样我们就得到的我们想要的内容,但是这些数据太少了对吧,如果我们需要更多的数据我们就需要更多的页面的评论,那么 下一页 是不是能符合我们的需求呢?
同样我们也要定位到下一页
的标签还是用上面的方法,但是我们发现这个定位太复杂了,越复杂越容易报错,那我们往前面看一点,我们看他的class
class也很长对吧 但是有特殊两个 zbnt 和znxt 通过查找我们发现 zbnt有两个选项,这肯定不行,幸运的是znxt是唯一的。但是他有一个问题,就是他代表的不是一个完整的标签那我们肯定也是选不到的,但是可以在前面加一个 . 选全部!
next_page = self.driver.find_element_by_css_selector(".znxt") # 下一页标签
next_page.click() # selenium方法 点击这一行代表的元素
在添加代码执行后他给我报错了,element click intercepted
元素点击被拦截,这个问题挺抽象的,明明定位到了却不能点击?在查阅资料(Google)后知道了,可能是标签上可能被什么不知名的元素遮挡了,所以我们无法点击,我们要驱动Java-scrapy
来点击,
# arguments[0].click(); 是Java scrapy的一个语法,意思是 方法将元素的引用作为参数 [0] 以及要执行的方法 ,我们后面的next_page位置就是 0 如果后面还有其他标签(sss) 那么他的位置就是 1
self.driver.execute_script("arguments[0].click();", next_page#, sss)
ps:selenium click()
不起作用是常态
这样我们就能正常访问了 ,这下就没有报错,并且正常点击到下一页了!,先在我们缺的就是一个循环和文件写入了,我们把它补上!
import time
from selenium import webdriver
url = 'https://music.163.com/#/song?id=86369'
class CloudMusic:
def __init__(self, url, number):
self.url = url
self.number = number
self.driver = webdriver.Edge(executable_path="./msedgedriver.exe") # 创建驱动器
def get_content(self):
self.driver.get(url) # 请求网页
self.driver.switch_to.frame(0) # 进入ifram标签
for i in range(self.number): # 爬取多少页
commons = self.driver.find_elements_by_css_selector('div.cnt.f-brk') # 提取评论链接 加 s
# print(commons)
for common in commons:
with open("偏爱.txt", "at", encoding="utf8")as f: # 文件名自行修改 追加写入
f.write(f"{common.text}\n") # 写入文本
next_page = self.driver.find_element_by_css_selector(".znxt") # 单数 不加s
self.driver.execute_script("arguments[0].click()", next_page)
time.sleep(1) # 加一个延迟 ,避免网速太慢页面没刷新,1s比较短
self.driver.quit() # 执行完毕退出
if __name__ == '__main__':
spider = CloudMusic(url, 10)
spider.get_content()
这样我们就得到了,前十页的评论信息!