在 ubuntu 中设置 selenium 和 ChromeDriver

作者: , 共 5536 字 , 共阅读 0

安装 selenium ,使用 requestium 来调用 selenium 程序更为简单,因此可一起安装:

sudo -E pip3 install selemium requestium

接下来主要是安装浏览器以及对应的驱动程序(即 driver )。系统环境为 ubuntu 20.04 和 Python 3.8。执行日期为 2024-01-11。

1、安装 Chrome 和 chromedriver

首先安装 Chrome :

wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb

下面的脚本可检查 Chrome 版本, 2024-01-11 时 Chrome 的 stable 版本是: Google Chrome 120.0.6099.216。

google-chrome --version

1.1、自动安装 ChromeDriver

接下来需要安装驱动 Chrome Driver ,它用于和 Google Chrome 交互,必须安装。 webdriver-manager 可以自动识别 Chrome 版本并安装相关驱动:

sudo -E pip3 install webdriver-manager

然后这么使用:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

options = Options()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(options, service)

driver.get("https://baidu.com")
print(driver.title)
driver.close()

但这里面有很多变数,主要是网络条件,包括是否可访问外网(相对局域网而言),是否可以访问外网(相对境内)。我测试就未成功。

1.2、手动安装 ChromeDriver

如果自动安装收到网络条件等因素不成功,我们只能手工安装 ChromeDriver。

按照大部分教程,我们可以在https://chromedriver.storage.googleapis.com/index.html这里找到对应版本的 driver 下载即可。但不幸的是,( 2024-01-11 )此处的最新版本只到 114.0.5735.90 ,并没有我们需要的 120.0.6099.216。(直接 apt 安装的 Chrome 版本又太低,同样在这里找不到对应的 driver )。

然后 Google 提供最新版本 Chrome 的页面https://googlechromelabs.github.io/chrome-for-testing/,其 stable 版本是 120.0.6099.109。120.0.6099.216 版本被标记为 stable(upcoming),其 driver 还不提供下载。

但经测试, 120.0.6099.109 的 ChromeDriver 驱动也可用于 120.0.6099.216 版的 Chrome 浏览器。所以我们安装 109 即可。直接下载解压缩到某个位置即可。

2、测试 requestium 效果

requestium 集成了 request 和 selenium。标准测试代码:

from requestium import Session, Keys

# 创建一个新的session
s = Session(webdriver_path='./geckodriver',
            browser='firefox',
            default_timeout=15,
            webdriver_options={'arguments': ['headless']})

# 访问登录页面
s.driver.get('https://baidu.org')

# 等待页面加载完成
s.driver.wait_for_page_load()

# 打印出当前页面的URL,确认是否登录成功
print(s.driver.title)

测试不成功,提示:

TypeError: __init__() got multiple values for argument 'options'

主要原因是 python 3.8 只能安装 requestium 0.2.x 版本,它只适配了 selenium 3.x。但最新的 selenium 4.x 改动了初始化方式,导致 Session 无法正常初始化。

3、测试 selenium 效果 以及教程

3.1、初始化 selenium

注意网上很多实例都是基于 selenium 3 或以下版本。4.0 版本改动很大,初始化方式也被改动了, Chrome 类不再接受 executable_path 的传入参数,必须通过 Service 对象传入:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service

options = Options()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')

service = Service(executable_path="/opt/3rd/chromedriver-linux64/chromedriver")
driver = webdriver.Chrome(options, service)

driver.get("https://baidu.com")
print(driver.title)

另外, Service 会在本地建立一个服务,因此不能使用代理。包括环境变量https_proxyhttp_proxy设置都必须取消,否则会提示无法访问端口。

另外注意,这样初始化的 driver 是单实例的,也就是每次只操作当前访问或跳转的网页。

3.2、填写登录信息

selenium 最重要的就是提供登录,可以模拟用户输入和点击

username = driver.find_element("name", "username")
username.send_keys("myname")

submit = driver.find_element("xpath", "//div[@class='btn']/a")
submit.click()

但我在一个网页的测试中,上述操作总是不成功,提示selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable,也一直没找到原因。最后用间接方法实现:

driver.execute_script('arguments[0].value = "myname";', username)
driver.execute_script('arguments[0].click();', submit)

3.3、等待跳转

在点击登录后,有些网站会有多轮跳转,在完成跳转之前操作会出问题。因此需等待跳转完成。这时候可通过检查特定元素对象存在性,下面是检查一个 id 为 step 的元素是否存在,等待时间为 30 秒,超时将记录一个错误信息:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

try:   
    wait = WebDriverWait(driver, 30)
    wait.until(EC.visibility_of_element_located(("id", 'step')))
except Exception as e:
    log.error("登录后迟迟无法跳转到主页,错误:%s。当前页面:%s",
        e, driver.page_source)

3.4、和 requests 的结合

requestium 集成了 requests 和 selenium。但 Python 3.8 下无法使用。暂时略过。

下面代码可以将 selenium 的 cookie 信息挪到 requests ,然后读取网页数据,由于不会渲染网页,速度比 driver.get 要快很多:

import requests 

session = requests.Session()

for cookie in driver.get_cookies():
    session.cookies.set(cookie['name'], cookie['value'])

content = session.get("url").content.decode()
print(content)

而且我们还可以把 cookies 存下来,下次直接读取,避免再次登录操作。

3.5、进阶操作

3.5.1、跳转打开新网页
driver.switch_to.window("windowName")
3.5.2、页面内的 iframe
driver.switch_to.frame("frameName")

3.6、selenium 的常用函数

基本操作和网页内容:

  • driver.get(url):访问网页。
  • driver.page_source :网页源码( html )
  • driver.title :网页标题
  • driver.current_url :当前网页地址

查找元素:

  • driver.find_element(type, info): type 可以为"name", "id", "class name", "xpath", "css selector",用于查找页面上指定元素。可参考官方文档: Locating Elements。其中 css selector 最直观。
  • driver.find_element 可以连着使用:driver.find_element("id", "form").find_element("name", "username")
  • driver.find_elements 类似,只是返回符合条件的多个元素的列表。

元素上操作:

  • ele.send_keys("abc"):填写元素(通常是一个 input )的内容。
  • ele.clear():清除元素(通常是一个 input )的内容。
  • ele.click():点击元素。
  • ele.select_by_index(index):选择选择项。还可以 select_by_value/select_by_visible_text。
  • ele.get_attribute("value"):获取元素的属性。

操作 cookie (一个 cookie 是一个{name, value}的字典):

  • driver.add_cookie({name, value})
  • driver.get_cookies():获取所有 cookie 列表。
  • driver.get_cookie(name):获取指定 cookie

Q. E. D.

类似文章:
编程 » django, requests, python
这里的 requests 是指 Python 的 requests 包。
IT » css, 打印
最近碰到这个问题,我需要将网页打印成 PDF 文件。Chrome 可直接将网页保存(打印)为 PDF (无需安装 Adobe ),但式样跟网页上显示的截然不同。我测试了一下用法,了解了其中的一些原理和解决方法,总结如下。
编程 » python, requests, django
在 Python 里,我们可以用request.post提交json数据:
命令行参数的初步说明,请参考argparse 模块用法实例详解,写的很清晰而详细。
IT » ubuntu, 网络代理
下面命令设置环境变量http_proxyhttps_proxyhttp://127.0.0.1:7890,分别用于访问非加密和加密网址。目前大部分网址都是加密网址。
IT » apt, pip, python, ubuntu
正常而言,大家都是用 pip 来安装 python 的包。但有时候无意中(通常是为安装某个特定的软件,根据软件的安装提示),会使用 apt 安装 python 包。而且其实很多包都可以通过 apt 来安装的,名字就是包名再加python3-的前缀。安装后的库以及依赖项位于/usr/lib/python3/dist-packages目录下。比如 apt 安装 requests 包:
相似度: 0.078
IT » github
github 自从废除用户名密码直接登录之后,就乱了很多。直接用户名密码会提示:
IT » Python, Ubuntu
主要是update-alternatives命令的使用。
编程 » C++, boost, 命令行
我们用boost的命令行库program_options解析命令行,在解释布尔命令行时使用下面代码:
Python的命令行包argparse内置了-h, --help命令。但它没有分组,和其它的命令混在一起,并且显示在最前面。我更喜欢把它放在单独的「LOG 和帮助」分组:
碎碎念 » 比亚迪
2018 年底购入的比亚迪, 2023 年是第五年,总里程 54630 ,其中 2023 年里程 1.2 万公里。充电费用 4890 元,合计每公里约 0.4 元。
周末绿野童军一群人走了一个精品小环线。从龙泉峪公交车站出发,下到水泉沟入口,沿冰面往下走到黑龙潭,再上爬到长城,沿长城返回。整个路线全长 8 公里,爬升只有 350 米,是一条非常值得推荐的小环线。