外观往往和事物的自身齐全不符,世人都容易为外表的装璜所坑骗。—— 莎士比亚《威尼斯商人》
一. 概述
上一篇文章【爬虫】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 /opt
total 8228
drwxr-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 bin
drwxr-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.1
drwxrwxrwx 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 webdriver
from selenium.webdriver import DesiredCapabilities
if __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 etree
from selenium import webdriver
from selenium.webdriver import DesiredCapabilities
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC # 和上面 WebDriverWait 一起用的
from selenium.webdriver.support.wait import WebDriverWait
def 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 html
def 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 result
if __name__ == '__main__':
url = "https://www.toutiao.com/a6969138023774667264/"
result = get_news_content(url)
print(result)
参考文档:
https://github.com/SeleniumHQ…