前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >selenium抓取网易云音乐评论及歌曲信息

selenium抓取网易云音乐评论及歌曲信息

作者头像
code2roc
发布2023-07-19 14:28:00
3540
发布2023-07-19 14:28:00
举报

最近在研究springboot,就想着结合爬虫做个网易云音乐在线搜索的功能,先上波效果图把

抓取使用的是selenium+chormedriver,也试过phantomsjs,但是对于页面的元素等待好像不支持,加上chromedriver有无界面模式,所以就选择这种搭配方式。抓取的时候首先按是设置chormedriver的路径与无界面模式,需要放在电脑chorme浏览器的安装目录下

代码语言:javascript
复制
 String loadurl = MessageFormat.format("https://music.163.com/#/search/m/?s={0}&type=1", URLEncoder.encode(musicname));
        String DRIVER_PATH = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chromedriver.exe";
        System.setProperty("webdriver.chrome.driver",DRIVER_PATH);
        ChromeOptions opt = new ChromeOptions();
        //使用谷歌的无头模式 PhantomJS后续高版本不在收到seleunim的支持,且开源暂停开发
        opt.addArguments("headless");
        WebDriver driver = new ChromeDriver(opt);

然后访问网易云音乐主页,其中的url是通过构造搜索形式的地址直接访问,type=1是指歌曲搜索,注意网页中的搜索列表内容部分是内嵌的iframe,需要进行浏览器的dom切换

代码语言:javascript
复制
  //切换到内嵌iframe中
        driver.switchTo().frame("g_iframe");

接下来就是对搜索列表的内容dom结构分析,首先确定外层容器class=srchsongst,里面的各条数据的class为以item开头,后面加标识的div

代码语言:javascript
复制
 List<WebElement> songlist = driver.findElement(By.className("srchsongst")).
findElements(By.cssSelector("div[class^='item']"));

定位到行之后,需要对歌曲的各个列进行元素抽取,首先获取歌曲id,这个id后面有作用,因为歌曲id的div没有特别唯一的class或者其他属性,不能靠常规的css选择来定位,找寻顾虑后,发现id的容器始终是行数据的第1个div,所以可以采用chidren列表的方式取到目标div

代码语言:javascript
复制
 String songid =  song.findElement(By.cssSelector("div:nth-child(1)")).
findElement(By.tagName("a")).getAttribute("data-res-id");

下面还要获取歌曲的url(用来进一步获取评论),歌曲名称,作者,专辑,时间,采用常规的css选择器就可以

代码语言:javascript
复制
String url = URLEncoder.encode(song.
findElement(By.cssSelector("div[class$='w0']")).findElement(By.tagName("a")).getAttribute("href"));
String musciname = song.findElement(By.cssSelector("div[class$='w0']")).
findElement(By.tagName("b")).getAttribute("title");
String author = song.findElement(By.cssSelector("div[class$='w1']")).
findElement(By.className("text")).getText();
String album = song.findElement(By.cssSelector("div[class$='w2']")).
findElement(By.tagName("a")).getText();
String time = song.findElement(By.cssSelector("div:nth-child(6)")).getText();

获取其他三个栏位,歌手专辑,歌单原理差不多,只需要模拟鼠标事件点击tab栏进行切换,看下代码

代码语言:javascript
复制
//歌手
        driver.findElement(By.cssSelector("a[data-type='100']")).click();
        //等待页面数据加载完成
        WebDriverWait wait = new WebDriverWait(driver, 20);
        //com.google.guava版本问题引起的传入函数条件不满足泛型
        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("ul[class^='m-cvrlst']")));
        List<WebElement> authorinfolist = driver.
findElement(By.cssSelector("ul[class^='m-cvrlst']")).findElements(By.cssSelector("div[class^='u-cover']"));
        List<AuthorInfo> authorlist = new ArrayList<AuthorInfo>();
        for(WebElement author:authorinfolist){
            AuthorInfo authorInfo = new AuthorInfo();
            String imageurl = author.findElement(By.tagName("img")).getAttribute("src");
            String authorname = author.findElement(By.tagName("span")).getAttribute("title");
            authorInfo.setAutorname(authorname);
            authorInfo.setImageurl(imageurl);
            authorlist.add(authorInfo);
        }

其中a[data-type='100']代表的就是栏目标签,type的值不同代表栏位不同,wait.unti方法就是之前所说的等待页面某个元素加载的方法,因为切换栏位可能由于ajax加载或者页面的数据部分刷新,可能数据没有完全展示出来就进行dom分析,导致数据抓不到,其他2个栏目抓取方法大同小异,最后会给大家贴上源码地址。

抓取完毕列表,就可以开始访问歌曲详细页面进行评论抓取了,老规矩,先分析dom结构,这边因为不需要等待元素,所以使用了phantomjs,先进行一系列设置

代码语言:javascript
复制
  //抓取网页
        DesiredCapabilities dcaps = new DesiredCapabilities();
        //ssl证书支持
        dcaps.setCapability("acceptSslCerts", true);
        //截屏支持
        dcaps.setCapability("takesScreenshot", true);
        //css搜索支持
        dcaps.setCapability("cssSelectorsEnabled", true);
        //js支持
        dcaps.setJavascriptEnabled(true);
        try {
            //驱动支持
            dcaps.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
                    ResourceUtils.getURL("src/main/resources/static/plugins/phantomjs/").getPath()+"phantomjs.exe");
        }catch (Exception e){
            System.out.println("phantomjs error");
            e.printStackTrace();
        }
        //创建无界面浏览器对象
        PhantomJSDriver driver = new PhantomJSDriver(dcaps);
        driver.get(url);
        //切换到内嵌iframe中
        driver.switchTo().frame("g_iframe");

首先定位外层容器地div class=m-cmmt,再到行数据div class=itm,再定位到最底层容器cntwrap,评论内容是以cnt开头class的div,评论时间是time开头class的div

代码语言:javascript
复制
 String nickname = content.findElement(By.tagName("a")).getText();
 String commentcontent =content.findElement(By.cssSelector("div[class^='cnt']")).
getText().replace(nickname+":","");
 String commentdate = content.findElement(By.cssSelector("div[class^='time']")).getText();

上个效果图

最后讲下下载功能,网易云有一个外链播放地址http://music.163.com/song/media/outer/url?id=,id后面传之前我们获取到的歌曲id就可以,打开是个外链播放器,直接下载既可以

注:chromedriver和电脑安装的浏览器版本要一致,下面给出对应列表连接

对应列表:https://blog.csdn.net/yoyocat915/article/details/80580066

驱动列表:http://npm.taobao.org/mirrors/chromedriver/

源码地址

前端:https://github.com/grassprogramming/yblog/tree/master/main/resources/static/pages/spider/music

后端:https://github.com/grassprogramming/yblog/tree/master/main/java/com/blog/spider/controller

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-08-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档