外观往往和事物的自身齐全不符,世人都容易为外表的装璜所坑骗。—— 莎士比亚 《威尼斯商人》
一. 概述
上一篇文章 【爬虫】python+selenium+firefox应用与部署详解 介绍了 selenium
传统形式部署与应用,须要装置浏览器、装置浏览器对应的驱动等,对于我来说配置还是比拟繁琐,有没有没有简略的配置形式呢?有,那就是应用 docker
来部署,接下来将介绍如何应用 docker
部署 python + selenium + firefox-headless
。
二. docker 装置 selenium/standalone-firefox
selenium docker hub 地址:https://hub.docker.com/u/sele...
拜访下面的地址,抉择一个对应浏览器镜像,这里抉择 selenium/standalone-firefox
,如下图所示:
疾速开始
更多配置与应用能够查看 github:https://github.com/SeleniumHQ...
应用上面的命令启动一个
Firefox
的docker
容器:$ docker run --name firefox -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-firefox:3.141
- 拜访 http://localhost:4444 测试
webDriver
,如下图所示:
- 拜访 http://localhost:4444/wd/hub/... 跳转到 selenium 控制台,如下图所示:
留神:
- 当为蕴含浏览器的镜像执行docker运行时,请应用标记
--shm-size 2g
来应用主机的共享内存- 始终应用带有残缺标签的 Docker 镜像来固定特定的浏览器和网格版本。
为什么须要设置 --shm-size 2g
:
这是一个已知的解决方案,以防止在docker容器内浏览器解体,2gb的shm大小是任意的,但已知能够很好地工作,您的特定用例可能须要不同的值,倡议依据您的须要调整这个值。
能够应用上面的命令进入到 firefox 容器中:
docker exec -it firefox bash
应用上面命令,能够看到容器中曾经装置好了 firefox
和 geckodriver
:
seluser@67be1f8cd61f:/opt$ ls -al /opttotal 8228drwxr-xr-x 1 root root 4096 Jul 29 08:49 .drwxr-xr-x 1 root root 4096 Aug 15 08:02 ..drwxr-xr-x 1 root root 4096 Jul 29 08:52 bindrwxr-xr-x 7 root root 4096 Jul 29 08:49 firefox-latest-rwxr-xr-x 1 1000 1000 8401832 Apr 8 22:01 geckodriver-0.29.1drwxrwxrwx 1 root root 4096 Jul 29 08:44 selenium
三. 应用 webdriver.Remote() 配置近程浏览器
selenium
提供了 webdriver.Remote()
通过发送命令到近程服务器来管制浏览器,能够使执行测试的机器和发送测试命令的机器独立开来。
对于 webdriver.Remote()
的配置应用非常简单,不须要像后面文章提到的指定各种配置,其参数默认如下:
selenium.webdriver.remote.webdriver.WebDriver def __init__(self, command_executor: str = 'http://127.0.0.1:4444/wd/hub', desired_capabilities: Any = None, browser_profile: Any = None, proxy: Any = None, keep_alive: bool = False, file_detector: Any = None, options: Any = None) -> Any
应用示例如下:
from selenium import webdriverfrom selenium.webdriver import DesiredCapabilitiesif __name__ == '__main__': driver = webdriver.Remote( # 指定近程浏览器的地址 command_executor='http://localhost:4444/wd/hub', # 指定冀望的浏览器类型,这里装置的是 firefox 所以指定firefox desired_capabilities=DesiredCapabilities.FIREFOX, ) # 发送申请 driver.get("https://www.baidu.com") # 获取网页源码 html = driver.page_source print(html) # 获取网页title title = driver.title print(title) # 百度一下,你就晓得 # 获取以后网页的 url current_url = driver.current_url print(current_url) # https://www.baidu.com/ # 退出驱动,敞开所有关联的窗口 driver.quit()
当应用 driver.close()
敞开以后窗口的时候,能够看到 selenium 控制台会产生一个会话,并且没有主动敞开会话,如下图所示:
这里运行了三次产生了三个会话,如果应用 driver.quit()
会主动敞开关联的所有会话,不会保留会话 id 在控制台。
driver = webdriver.Remote() 罕用办法与属性:
driver.get(url)
在以后浏览器会话中拜访传入的url地址。
用法:driver.get('https://www.baidu.com')
driver.close()
敞开浏览器以后窗口。
driver.quit()
退出webdriver并敞开所有窗口。
driver.refresh()
刷新以后页面。
driver.title
获取当前页的题目。
driver.page_source
获取当前页渲染后的源代码。
driver.current_url
获取以后页面的url。
driver.window_handles
获取以后会话中所有窗口的句柄,返回的是一个列表。
四. python + selenium 配置近程浏览器获取今日头条数据
上一篇文章中获取今日头条数据的代码配置近程浏览器批改如下:
from lxml import etreefrom selenium import webdriverfrom selenium.webdriver import DesiredCapabilitiesfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditions as EC # 和上面WebDriverWait一起用的from selenium.webdriver.support.wait import WebDriverWaitdef html_selenium_firefox(url): """ 依据 url 应用 selenium 获取网页源码 :param url: url :return: 网页源码 """ driver = webdriver.Remote( # 指定近程浏览器的地址 command_executor='http://localhost:4444/wd/hub', # 指定冀望的浏览器类型,这里装置的是 firefox 所以指定firefox desired_capabilities=DesiredCapabilities.FIREFOX, ) # 发送申请 driver.get(url) # 显式期待:显式地期待某个元素被加载 wait = WebDriverWait(driver, 20) wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'article-content'))) wait.until(EC.presence_of_element_located((By.TAG_NAME, 'span'))) # 获取网页源码 html = driver.page_source # 敞开浏览器开释资源 driver.quit() return htmldef get_news_content(url): html = html_selenium_firefox(url) tree = etree.HTML(html) title = tree.xpath('//div[@class="article-content"]/h1/text()')[0] # xpath 查找没有 class 的元素:span[not(@class)] pubtime = tree.xpath('//div[@class="article-meta mt-4"]/span[not(@class)]/text()')[0] # xpath 查找 class="name" 的元素:span[@class="name"] source = tree.xpath('//div[@class="article-meta mt-4"]/span[@class="name"]/a/text()')[0] # xpath 某个标签中的所有元素://div content = tree.xpath('//article')[0] # 解决 content 乱码问题 content = str(etree.tostring(content, encoding='utf-8', method='html'), 'utf-8') # 提取 content 中所有图片的地址 images = etree.HTML(content).xpath('//img/@src') result = { "title": title, "pubtime": pubtime, "source": source, "content": content, "images": images, } return resultif __name__ == '__main__': url = "https://www.toutiao.com/a6969138023774667264/" result = get_news_content(url) print(result)
参考文档:
https://github.com/SeleniumHQ...