需要了解的知识:Python、H5、C3、JS
本文使用开发环境:windows11、Python 3.11.4、PyCharm 2023.2、Selenium 4.3.0
Selenium是什么?
Selenium是一个开源的和便携式的基于浏览器的自动化软件测试工具,它通常用来编写web应用的自动化测试。Selenium不是一个单一的工具,而是一套工具,帮助测试者更有效地基于web的应用程序的自动化(相当于模拟人为自动操作浏览器)。
WebDriver是什么?
Selenium WebDriver是Selenium Tool套件中最重要的组件。WebDriver提供了另外一种方式与浏览器进行交互。那就是利用浏览器原生的api,封装成一套更加面向对象的Selenium WebDriver API,直接操作浏览器页面里的元素,甚至操作浏览器本身。但是不同的浏览器厂商,对Web元素的操作和呈现存在差异,这就要求Selenium WebDriver要分浏览器厂商的不同,提供不同的实现,如Chrome有专门的ChromeDriver,Firefox有FirefoxDriver等。
下载selenium
PyCharm中找到本地命令行,输入以下命令安装selenium包
pip install selenium==4.3.0 #安装selenium 4.3.0
pip list # 查看已安装的Python包
下载WebDriver
我这里使用的是火狐浏览器,所以需要下载FirefoxDriver,win64位的,根据自己的开发环境下载对应的驱动,谷歌浏览器需要查看浏览器的版本,下载相同版本的驱动
火狐浏览器自动化驱动下载地址https://github.com/mozilla/geckodriver/releases/
谷歌浏览器自动化驱动下载地址http://chromedriver.storage.googleapis.com/index.html
将下载好的驱动解压,放在Python安装目录下,这里下载的版本是geckodriver-v0.33.0-win64
配置环境变量
在系统变量中找到Path,将驱动放置的目录粘贴进去,保存即可,需要重启一下PyCharm,不然导入WebDriver可能无法识别
测试环境
输入以下代码并执行,如果浏览器自动打开了,说明环境配置安装成功。注意:id需要自己去修改
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('https://music.163.com/#/song?id=1234567')
有界面爬取网页
直接上代码,有界面爬取评论,默认会弹出浏览器界面
from selenium import webdriver
# By没有定义,声明By模块
from selenium.webdriver.common.by import By
import re
import time
driver = webdriver.Firefox()
driver.get('https://music.163.com/#/song?id=1234567')
# 切换到嵌套网页iframe里面
driver.switch_to.frame(0)
for page in range(5):
lists = driver.find_elements(By.CLASS_NAME, 'itm')
for contents in lists:
content = contents.find_element(By.CLASS_NAME, 'cnt').text
new_content = re.findall(':(.*)', content)[0]
print(new_content)
print("=" * 100)
time.sleep(1) # 休息一秒再点击
print("-" * 100)
js = 'document.documentElement.scrollTop = document.documentElement.scrollHeight'
driver.execute_script(js) # 执行js模拟人为滑动浏览器
driver.find_element(By.CLASS_NAME, 'znxt').click()
注意以上代码需要导入By模块,具体文档可以看下面这个selenium-python中文文档
selenium-python中文文档https://python-selenium-zh.readthedocs.io/zh_CN/latest/
无界面爬取网页
因为有界面爬取,默认每次都需要打开浏览器,所以爬取速度会慢一点,所以使用无界面自动化爬取评论。具体代码如下
# 君子协议,在网址后面加上robots.txt就能看到
# User-agent: *
# Disallow: /prime/m/gift-receive
import re
import time
import random
from selenium import webdriver # selenium 模拟人为自动爬取
# selenium 默认是有界面的,每次都要打开界面,爬取比较慢
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.by import By # By没有定义,声明By模块
# 获取浏览器对象
def get_browser():
# 设置firefox为无界面浏览器
firefox = Options()
firefox.add_argument('--headless')
firefox.add_argument('--disable-gpu')
# 开启浏览器
browser = webdriver.Firefox(options=firefox)
return browser
# 模仿人为操作浏览器
def get_click(browser):
js = 'scrollTo(0,document.body.scrollHeight)'
browser.execute_script(js)
browser.find_element(By.CLASS_NAME, 'znxt').click()
# 下载保存评论
def save_comment(i, comment):
# 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。
# 如果该文件不存在,创建新文件进行写入。
with open('网易云评论.txt', 'a', encoding='utf-8') as fp:
fp.write(f"第{i}条评论-->" + comment)
fp.write('\n')
# 获取评论
def get_comment(song_id, browser, pages):
url = f'https://music.163.com/#/song?id={song_id}'
browser.get(url) # 利用get请求 请求浏览器的一个网页
browser.switch_to.frame(0) # 切换到嵌套网页里面
i = 1
# 遍历页数为0 到 pages - 1
for page in range(pages):
# 找到itm这个类名的所有元素里面的内容 是一个列表
lists = browser.find_elements(By.CLASS_NAME, 'itm')
for list in lists:
comment = list.find_element(By.CLASS_NAME, 'cnt').text # 用户 + 评论
user = list.find_element(By.CLASS_NAME, 's-fc7').text # 用户
# :(.*) 代表冒号后面的所有内容, 用户评论
new_content = re.findall(':(.*)', comment)[0]
print(f"第{i}条评论-> {user}: {new_content}")
i += 1
save_comment(i, comment)
# 休眠时间为2 - 4之间随机整数, 调用函数点击下一页
time.sleep(random.randint(2, 4))
print("-" * 100)
get_click(browser)
if __name__ == '__main__':
song_id = 123456 # 歌曲 ID 搜索音乐 浏览器上面会出现歌曲id
browser = get_browser()
pages = int(input("请输入准备下载的页数:"))
get_comment(song_id, browser, pages)
browser.close() # 关闭浏览器
browser.quit() # 杀死chrome浏览器的连接桥(chromedriver)的进程