zoukankan      html  css  js  c++  java
  • 网易云音乐 抓取成功,按评论数排序

    可以生成外链播放器

    <iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=298 height=52 src="//music.163.com/outchain/player?type=2&id=151646&auto=0&height=32"></iframe>

    需要保存的项有:
    m_name :歌名
    m_singer:歌手
    vote 评论数
    url : 链接
    播放功能
    通过相似歌曲查找其它歌,
    歌名
    //*[@id="auto-id-xRQFDgyFzdwbznWT"]/div[3]/div[1]/div/div/div[1]/div[1]/div[2]/div[1]/div/em
    //*[@id="auto-id-sQbhxsxtnM7vJTti"]/div[3]/div[1]/div/div/div[1]/div[1]/div[2]/div[1]/div/em
    //*[@id="auto-id-koka4uE8EU8gmROm"]/div[3]/div[1]/div/div/div[1]/div[1]/div[2]/div[1]/div/em
    /song?id=29431270
    相似歌曲是相对路径:
    豆瓣查看网页源代码有xpath,但是云音乐没有
    <a href="/song?id=393705" title="英雄的黎明"
    爬取的是框架外的代码。
    不是iframe里面的代码
    <iframe name="contentFrame" id="g_iframe" class="g-iframe" scrolling="auto" frameborder="0" src="about:blank"></iframe>
    注意有2个iframe
    先下载网页源代码,注意不是框架源代码。
    分析:
    js

    selenium和 phantomjs
    iframe content is not returned as a part of html.
    The problem is that iframe content is not returned as a part of html. You can either try to fetch iframe content directly (by its src), or use render.json endpoint with iframes=1 option:
    import parsel
    # ... yield SplashRequest(url, self.parse_result, endpoint='render.json', args={'html': 1, 'iframes': 1}) def parse_result(self, response): iframe_html = response.data['childFrames'][0]['html'] sel = parsel.Selector(iframe_html) item = { 'my_field': sel.xpath(...), # ... }
    /execute endpoint doesn't support fetching iframes content as of Splash 2.3.3.
    note that xpath shouldn't include anything outside iframe - process iframe content as a separate document
    Also, you may need to take a different iframe; I wrote ['childFrames'][0] as an example - index could be different.
    If the web page has mutiple iframes, and iframe you're interested in is not the first, you'll have to use an appropriate index instead of 0
    注意
    title=[u'u6545u4e61u7684u539fu98ceu666f']是一个元组,
    列表用[ ]标识
    如果想要打印出来,需要加index
    logging.info("title=%s" % sel.xpath('//div[@class="tit"]/em/text()').extract()[0])
    找歌手
    //div[@class="cnt"]/p[1]/span/@title
    p1表示是div下面的第一个p元素,注意序号是从1开始的,
    而且选取属性用@title,不是@title/text()

    现在抓取了其ifame里面的页面,但是里面的评论数没有!
    <i><span id="cnt_comment_count">评论</span></i>
    正常应该是
    <i>(<span id="cnt_comment_count">14115</span>)</i>
    评论框也没有
    <div class="n-cmt" id="comment-box" data-tid="R_SO_4_393705" data-count="0"></div>
    这个链接是
    附:
    爬评论分析过程
    chrome network 选择xhr过滤下,
    Initiator 标记请求是由哪个对象或进程发起的
    如果看不到initiator,点击关闭
    这个请求是一个post,有两个参数,params和encSecKey
    那么这两个参数是怎么获得的呢?
    从initiator一栏里可以看到这个请求的“发起人”是core.js
    一般这样的js都是没法看的,下载下来美化过后发现有两万多行,但是没关系,我们需要的只是部分数据。
    在这个js文件中搜索params和encSecKey
    那么问题就变成得到这个bua
    它是由window.asrsea这个函数得到的,可以看到有4个参数,如果研究每个参数肯定是痛苦的,也没有必要,可以先把它们输出来看一下,这时候就需要线上调试js,我选择了Fiddler,在Fiddler的AutoResponder页添加Rule,大概长这样
    之后网页加载使用的core.js文件就是我们本地的这个js文件了,而我们可以修改本地的这个文件来获得想要的数据
    如果有多个输出,就在页面的Headers中找到encSecKey的值,与控制台输出的对比下,就可以找到真正j50的输出了。
    就是下面这条了!
    发现rid就是R_SO_4_加上歌曲的id
    offset就是(评论页数-1) * 20
    按这样的方式可以得到其余三个参数
    如 第二个参数:
    010001
    第三个参数:
    00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7
    第四个参数:
    0CoJUm6Qyw8W8jud
    现在我们只要知道函数window.asrsea如何处理的就可以了
    定位到这个函数发现它其实是一个叫d的函数
    这里的i研究之后你会发现就是一个长度为16的随机字符串,既然是随机的,我就直接让他等于16个F了
    这个encText明显就是params,encSecKey明显就是encSecKey
    而b函数就是一个AES加密,经过了两次加密,
    第一次对d也就是那个json加密,key是第四个参数,第二次对第一次加密结果进行加密,key是i。在b函数中我们可以看到
    密钥偏移量iv是0102030405060708,模式是CBC,那么就不难写出对于这个json的加密了。
    接下来是第二个参数encSecKey,
    c (i, e,f)
    这里传入c的三个参数i是16个F,e是第二个参数,f是第三个参数(值见上),全部是固定的值
    那么无论歌曲id或评论页数如何变化,这个encSecKey都不随之发生变化
    encSecKey:
    3de07243e358cf9b6d5398c72774adcb086446650b4dd385df00a5331ae8358448d051fbe8efe36bb8f4eb22f61fd13e4db484b3fa516c81fd8c1e64058a0838b866f4e6adb449a7acb918dd02e63e795e48e99cb4c9edc57a0a7d79fa480a8d71cf679fe16ccd4e2472425f300c91ebff15e61407891b867da1d3cc8842e8ce
    至此,我们得到了所有的两个参数。
    No module named Crypto.Cipher
    sudo pip uninstall crypto
    sudo pip uninstall pycrypto
    sudo pip install pycrypto
    算法先通过createSecretKey生成一个16位的随机字符串作为密钥secKey,然后将明文text进行两次AES加密获得密文encText,因为secKey是在客户端上生成的,所以还需要对其进行RSA加密再传给服务端。
    url=http://music.163.com/#/song?id=393705
     
  • 相关阅读:
    MyBatis insert 返回主键的方法
    Linux实时网络监控工具:iftop
    深入理解Spring MVC 思想
    spring启动时加载字典表数据放入map
    mysql PROCEDURE ANALYSE() 用法
    http://www.cnblogs.com/shihaiming/
    maven 多模块项目
    分布式存储 CentOS6.5虚拟机环境搭建FastDFS-5.0.5集群(转载-2)
    Nginx1.8.0版本平滑升级新版本1.9.7
    Linux 添加Nginx 到 service 启动
  • 原文地址:https://www.cnblogs.com/elesos/p/7892291.html
Copyright © 2011-2022 走看看