题图:by cfunk44 from Instagram

在使用 Ajax 技术加载数据的网站中, JavaScript 发起的 HTTP 请求通常需要带上参数,而且参数的值都是经过加密的。如果我们想利用网站的 REST API 来爬取数据,就必须知道其使用的加密方式。破解过程需要抓包,阅读并分析网站的 js 代码。这整个过程可能会花费一天甚至更长的时间。

问:那么是否有办法绕过这机制,直接获取网站数据?
答:有的。使用 Selenium 库模拟浏览器行为来抓取网站数据,达到事半功倍的效果。

本文内容是利用 Selenium 爬取网易云音乐中的歌曲 《Five Hundred Miles》 的所有评论,然后存储到 Mongo 数据库。

0 前期准备

本文中所用到的工具比较多,所以我将其列举出来。

  • Selenium

Selenium 是一个 Web 应用程序自动化测试的工具。它能够模拟浏览器进行网页加载。所以使用其来帮助我们解决 JavaScript 渲染问题。

接下来就是安装 selenium, 使用 pip 安装是最方便的。

pip install selenium

  • Chrome 浏览器

在爬取数据过程中, 需要启动浏览器来显示页面。因此,电脑中需要一款浏览器。这里推荐使用 Chrome 浏览器。推荐使用 59 版本以上的 Chrome,当然能使用最新版本那最好不过,目前最新版本是 68。

  • Webdriver

Webdriver 是浏览器驱动。selenium 通过 Webdriver 来操作浏览器。因为我们使用的浏览器是 Chrome,所以需要下载 Chrome 浏览器对应的驱动。

下载地址:http://chromedriver.chromium.org/downloads

webdriver 下载解压完成之后,将其放到 Python 目录下的 Script 文件夹中。

点击查看大图


  • MongoDB

网易云音乐的评论数据总数都很大,十几万条数据比比皆是,甚至还有上百万条数据。所以需要将数据存储到数据库中,我选用的是 MongoDB。

  • pymongo

pymongo 是 Python 操作 MongoDB 的库。同样使用 pip 进行安装。

pip install pymongo

1 爬取思路

1)使用 Selenium 驱动 Chrome 浏览器打开需要爬取的页面。

2)获取页面中 最新评论 标签后面的评论总数,计算出一共有多少个分页, 方便统计。利用总评论数除以 20(每个页面显示 20 条评论),然后对结果进行向上取整。

3)爬取第一页面的评论的数据,然后存储到数据库中。

4)利用 Selenium 模拟点击下一页按钮,再继续爬取该页面的评论数据,并存储到数据库中。

5)一直循环点击,直到所有分页的数据都被爬取完成。

2 代码实现

我们要爬取的歌曲是 《Five Hundred Miles》,先找到其 url 地址,然后调用爬取函数。

if __name__ == '__main__':
   url = 'http://music.163.com/#/song?id=27759600'  # Five Hundred Miles
   start_spider(url)

使用 selenium 启动 Chrome 浏览器。

from selenium import webdriver

def start_spider(url):
   """ 启动 Chrome 浏览器访问页面 """
   """
   # 从 Chrome 59 版本, 支持 Headless 模式(无界面模式), 即不会弹出浏览器
   chrome_options = webdriver.ChromeOptions()
   chrome_options.add_argument('--headless')
   brower = webdriver.Chrome(chrome_options=chrome_options)
   """

   brower = webdriver.Chrome()
   brower.get(url)
   # 等待 5 秒, 让评论数据加载完成
   time.sleep(5)
   # 页面嵌套一层 iframe, 必须切换到 iframe, 才能定位的到 iframe 里面的元素
   iframe = brower.find_element_by_class_name('g-iframe')
   brower.switch_to.frame(iframe)
   # 获取【最新评论】总数
   new_comments = brower.find_elements(By.XPATH, "//h3[@class='u-hd4']")[1]

根据评论总数计算出总分页数。

# start_spider(url)
max_page = get_max_page(new_comments.text)

def get_max_page(new_comments):
   """ 根据评论总数, 计算出总分页数 """
   print('=== ' + new_comments + ' ===')
   max_page = new_comments.split('(')[1].split(')')[0]
   # 每页显示 20 条最新评论
   offset = 20
   max_page = ceil(int(max_page) / offset)
   print('一共有', max_page, '个分页')
   return max_page

接着循环抓取评论数据,首先抓取第 1 页的评论数据。

# start_spider(url)
current = 1
is_first = True
while current <= max_page:
   print('正在爬取第', current, '页的数据')
   if current == 1:
       is_first = True
   else:
       is_first = False
   data_list = get_comments(is_first, brower)

def get_comments(is_first, brower):
   """ 获取评论数据 """
   items = brower.find_elements(By.XPATH, "//div[@class='cmmts j-flag']/div[@class='itm']")
   # 首页的数据中包含 15 条精彩评论, 20 条最新评论, 只保留最新评论
   if is_first:
       items = items[15: len(items)]

data_list = []
   data = {}
   for each in items:
       # 用户 id
       userId = each.find_elements_by_xpath("./div[@class='head']/a")[0]
       userId = userId.get_attribute('href').split('=')[1]
       # 用户昵称
       nickname = each.find_elements_by_xpath("./div[@class='cntwrap']/div[1]/div[1]/a")[0]
       nickname = nickname.text
       # 评论内容
       content = each.find_elements_by_xpath("./div[@class='cntwrap']/div[1]/div[1]")[0]
       content = content.text.split(':')[1]  # 中文冒号
       # 点赞数
       like = each.find_elements_by_xpath("./div[@class='cntwrap']/div[@class='rp']/a[1]")[0]
       like = like.text
       if like:
           like = like.strip().split('(')[1].split(')')[0]
       else:
           like = '0'
       # 头像地址
       avatar = each.find_elements_by_xpath("./div[@class='head']/a/img")[0]
       avatar = avatar.get_attribute('src')

data['userId'] = userId
       data['nickname'] = nickname
       data['content'] = content
       data['like'] = like
       data['avatar'] = avatar
       print(data)
       data_list.append(data)
       data = {}
   return data_list

将第 1 页评论数据存储到 Mongo 数据库中。

# start_spider(url)
save_data_to_mongo(data_list)

def save_data_to_mongo(data_list):
   """ 一次性插入 20 条评论。
       插入效率高, 降低数据丢失风险
   """

   collection = db_manager[MONGO_COLLECTION]
   try:
       if collection.insert_many(data_list):
           print('成功插入', len(data_list), '条数据')
   except Exception:
       print('插入数据出现异常')

模拟点击“下一页”按钮。

# start_spider(url)
time.sleep(1)
go_nextpage(brower)
# 模拟人为浏览
time.sleep(random.randint(8, 12))
current += 1

def go_nextpage(brower):
   """ 模拟人为操作, 点击【下一页】 """
   next_button = brower.find_elements(By.XPATH, "//div[@class='m-cmmt']/div[3]/div[1]/a")[-1]
   if next_button.text == '下一页':
       next_button.click()

最后就一直循环爬取评论。

3 爬取结果

评论总数大概有 23W 条, 我又在代码中增加延时操作。所以爬取所有评论大概需要 69 个小时。目前我只跑了 9 个小时,我贴下暂时爬取的结果。

点击查看大图

4 扩展知识

这部分内容跟上述内容联系不大, 属于服务器技术范畴。如果你不感兴趣的话,可以直接跳过。另外,这部分内容是自己的理解。如果有讲错的地方,还请多多指出。

我们访问普通网站的整个过程:

点击查看大图

我们访问使用 Ajax 加载数据的网站的整个过程:

点击查看大图

温馨提示

点击『阅读原文』,查阅项目的源代码

转载声明:本文转载自「极客猴」,搜索「Geek_monkey」即可关注。

推荐阅读:

每天分享 Python 干货

Python 爬取网易云音乐所有评论相关推荐

  1. python爬取网易云音乐歌曲评论信息

    网易云音乐是广大网友喜闻乐见的音乐平台,区别于别的音乐平台的最大特点,除了"它比我还懂我的音乐喜好"."小清新的界面设计"就是它独有的评论区了------各种故 ...

  2. python爬取网易云音乐热评_python爬取网易云音乐评论

    本文实例为大家分享了python爬取网易云音乐评论的具体代码,供大家参考,具体内容如下 import requests import bs4 import json def get_hot_comme ...

  3. python爬取网易云音乐评论分析_python爬取网易云音乐评论

    本文实例为大家分享了python爬取网易云音乐评论的具体代码,供大家参考,具体内容如下 import requests import bs4 import json def get_hot_comme ...

  4. python爬虫网易云音乐评论再分析_爬取网易云音乐的评论后,竟有这种发现!

    原标题:爬取网易云音乐的评论后,竟有这种发现! 作者 | 志颖 责编 | 胡巍巍 用过网易云音乐听歌的朋友都知道,网易云音乐每首歌曲后面都有很多评论,热门歌曲的评论更是接近百万或者是超过百万条. 现在 ...

  5. python爬取网易云音乐飙升榜音乐_python爬取网易云音乐热歌榜 python爬取网易云音乐热歌榜实例代码...

    想了解python爬取网易云音乐热歌榜实例代码的相关内容吗,FXL在本文为您仔细讲解python爬取网易云音乐热歌榜的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:python,网易热歌榜 ...

  6. python爬取网易云音乐飙升榜音乐_python爬取网易云音乐热歌榜实例代码

    首先找到要下载的歌曲排行榜的链接,这里用的是: https://music.163.com/discover/toplist?id=3778678 然后更改你要保存的目录,目录要先建立好文件夹,例如我 ...

  7. python爬取网易云音乐排行榜数据

    python爬取网易云音乐排行榜歌曲及评论 网易云音乐排行榜歌曲及评论爬取 主要注意问题:selenium 模拟登录.iframe标签定位.页面元素提取. 在利用selenium定位元素并取值的过程中 ...

  8. 抄袭风波后 爬取网易云音乐看评论画风如何

    作者 | 小F 来源 | 法纳斯特(ID:walker398) 近日,民谣歌手花粥被爆出涉嫌抄袭. 具体的我就不细说了,音乐圈的抄袭风波也是喜闻乐见. 比如,李袁杰的「离人愁」,展展与罗罗的「沙漠骆驼 ...

  9. python爬音乐-用python爬取网易云音乐歌曲的歌词

    今天我来分享一下如何用python爬取网易云音乐歌曲的歌词,网易云音乐的歌词的爬取思路同前面介绍过的爬取网易云音乐的歌曲评论的爬取思路一致.由于两者的加密思路都是一致的,因此我们只需分析出被加密了的参 ...

最新文章

  1. 网络推广外包——网络推广外包专员面对外链发布更注重细节
  2. javascript-for-loop-example--reference
  3. 20201010《近代数学》第1节课 笔记
  4. linux jdk免安装配置,生产环境免安装jdk的使用方法
  5. JS实现的文章字符串中某个字符总个数统计在线小工具实例
  6. Surface Book 3现身3DMark:10nm架构升级
  7. 晨哥真有料丨为什么越优秀的女生越寡?
  8. 炸了!!又一 VSCode 神器面世!
  9. 计算机思维导论在线作业答案,大学计算机计算思维导论第讲习题及解析.pdf
  10. 大气海洋数值模式经验总结
  11. mysql语句中的注释方法_MySQL语句注释方式简介
  12. 这些曾盛极一时的经典软件,现在再看,还是记忆犹新
  13. war包的解压与打包
  14. 欧拉图论定理 公式及证明
  15. ESP8266-Arduino编程实例-2.8寸TFT LCD驱动(ILI9341控制器)
  16. Genexus第5篇-WebPanel
  17. Osg使用osgQt与Qt结合使用(附项目)(1)
  18. 面向对象的特点?对象模型、动态模型和功能模型3种模型之间的关系?
  19. 任务管理系统算法-Kahn’s algorithm for Topological Sorting(一)
  20. Word文档如何复制文字的格式

热门文章

  1. 工业互联网与工控安全
  2. eclipse下载网址收藏
  3. 科研写作——常见句式(五)
  4. 两类边界条件的OBVP求解方法
  5. 计算机网络基础结构;对等网的特点;网络的扩大;网络的拓扑结构;
  6. 阿里巴巴开源产品列表
  7. 【操作系统】程序执行过程
  8. 汇编语言-计算总平成绩
  9. LC 104. Maximum Depth of Binary Tree
  10. 曙光实习笔记:第一天