关于python爬虫:爬虫docker-部署-python-selenium-firefoxheadless

27次阅读

共计 4271 个字符,预计需要花费 11 分钟才能阅读完成。

外观往往和事物的自身齐全不符,世人都容易为外表的装璜所坑骗。—— 莎士比亚《威尼斯商人》

一. 概述

上一篇文章【爬虫】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…

  1. 应用上面的命令启动一个 Firefoxdocker 容器:

    $ docker run --name firefox -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-firefox:3.141
  2. 拜访 http://localhost:4444 测试 webDriver,如下图所示:

  1. 拜访 http://localhost:4444/wd/hub/… 跳转到 selenium 控制台,如下图所示:

留神:

  1. 当为蕴含浏览器的镜像执行 docker 运行时,请应用标记 --shm-size 2g 来应用主机的共享内存
  2. 始终应用带有残缺标签的 Docker 镜像来固定特定的浏览器和网格版本。

为什么须要设置 --shm-size 2g

这是一个已知的解决方案,以防止在 docker 容器内浏览器解体,2gb 的 shm 大小是任意的,但已知能够很好地工作,您的特定用例可能须要不同的值,倡议依据您的须要调整这个值。

能够应用上面的命令进入到 firefox 容器中:

docker exec -it firefox bash

应用上面命令,能够看到容器中曾经装置好了 firefoxgeckodriver

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…

正文完
 0