【python爬虫】设计自己的爬虫 4. 封装模拟浏览器 Selenium

这篇具有很好参考价值的文章主要介绍了【python爬虫】设计自己的爬虫 4. 封装模拟浏览器 Selenium。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

有些自动化工具可以获取浏览器当前呈现的页面的源代码,可以通过这种方式来进行爬取
一般常用的的有Selenium, playwright, pyppeteer,考虑到他们的使用有许多相同之处,因此考虑把他们封装到一套api中

先看基类

class BrowserSimulateBase:
    def __init__(self):
        pass

    def start_browser(self, is_headless=False, is_cdp=False, is_dev=False, proxy=None, is_socks5=False, *args, **kwargs):
        """
        启动浏览器。

        Args:
            is_headless (bool, optional): 是否开启无头模式。默认为 False。
            is_cdp (bool, optional): 是否使用 Chrome Devtools Protocol。默认为 False。
            is_dev (bool, optional): 是否启用调试模式。默认为 False。
            proxy (str, optional): 代理设置。默认为 None。
            is_socks5 (bool, optional): 是否使用 SOCKS5 代理。默认为 False。
            *args, **kwargs: 其他参数。

        Raises:
            NotImplementedError: 派生类需要实现该方法。
        """
        raise NotImplementedError

    # 启动页面
    def start_page(self, url):
        raise NotImplementedError

    # 显式等待
    def wait_until_element(self, selector_location, timeout=None, selector_type=None):
        raise NotImplementedError

    # 等待时间
    def wait_time(self, timeout):
        raise NotImplementedError

    # 等待时间
    def wait_for_time(self, timeout):
        raise NotImplementedError

    # 查找多个元素
    def find_elements(self, selector_location, selector_type=None):
        raise NotImplementedError

    # 查找元素
    def find_element(self, selector_location, selector_type=None):
        raise NotImplementedError

    # 输入框 输入内容并提交
    def send_keys(self, selector_location, input_content, selector_type=None):
        raise NotImplementedError

    # 执行js命令
    def execute_script(self, script_command):
        raise NotImplementedError

    # 浏览器回退
    def go_back(self):
        raise NotImplementedError

    # 浏览器前进
    def go_forward(self):
        raise NotImplementedError

    # 获取cookies
    def get_cookies(self):
        raise NotImplementedError

    # 添加cookies
    def add_cookie(self, cookie):
        raise NotImplementedError

    # 删除cookies
    def del_cookies(self):
        raise NotImplementedError

    # 切换选项卡
    def switch_tab(self, tab_index):
        raise NotImplementedError

    # 刷新页面
    def reload_page(self):
        raise NotImplementedError

    # 截图
    def screen_page(self, file_name=None):
        raise NotImplementedError

    # 关闭浏览器
    def close_browser(self):
        raise NotImplementedError

    # 获取页面内容
    def get_content(self):
        raise NotImplementedError

    # 点击
    def click(self, selector_location, selector_type=None):
        raise NotImplementedError

    # 拉拽动作
    def drag_and_drop(self, source_element, target_element):
        raise NotImplementedError

    # 拉拽动作
    def to_iframe(self, frame):
        raise NotImplementedError

Selenium是一个自动化测试工具,利用它可以驱动浏览器完成特定操作,还可以获取浏览器当前呈现的页面的源代码,做到所见即所爬 对一些JavaScript动态渲染的页面来说,这种爬取方式非常有效使用Selenium驱动浏览器加载网页,可以直接拿到JavaScript渲染的结果

下面是封装的类

class SeleniumSimulate(BrowserSimulateBase):
    def __init__(self):
        self.browser = None

    # 启动浏览器
    # is_headless 是否开启无头模式
    # is_cdp 是否使用cdp (Chrome Devtools Protocol)
    def start_browser(self, is_headless=False, is_cdp=False, is_dev=False, proxy=None, is_socks5=False, *args,
                      **kwargs) -> webdriver.Chrome:
        """
        启动 Chrome 浏览器。

        Args:
            is_headless (bool, optional): 是否开启无头模式。默认为 False。
            is_cdp (bool, optional): 是否使用 Chrome Devtools Protocol。默认为 False。
            is_dev (bool, optional): 是否启用调试模式。默认为 False。
            proxy (str, optional): 代理设置。默认为 None。
            is_socks5 (bool, optional): 是否使用 SOCKS5 代理。默认为 False。
            *args, **kwargs: 其他参数。

        Returns:
            webdriver.Chrome: 已启动的 Chrome 浏览器对象。
        """
        option = ChromeOptions()
        if is_headless:
            option.add_argument('--headless')
        elif is_cdp:
            option.add_experimental_option('excludeSwitches', ['enable-automation'])
            option.add_experimental_option('useAutomationExtension', False)
        elif proxy:
            if is_socks5:
                option.add_argument('--proxy-server=socks5://' + proxy)
            else:
                option.add_argument('--proxy-server=http://' + proxy)

        self.browser = webdriver.Chrome(ChromeDriverManager().install(), options=option)
        if is_cdp:
            self.browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
                'source': 'Object.defineProperty(navigator, "webdriver", {get:()=>undefined})'
            })

        self.browser.set_window_size(WINDOW_WIDTH, WINDOW_HEIGHT)
        return self.browser

    # 启动页面
    def start_page(self, url):
        """
       在浏览器中打开指定的 URL。

       参数:
       url (str): 要打开的网址。

       无返回值。
       """
        self.browser.get(url)

    # 显式等待
    # timeout等待的最长时间
    def wait_until_element(self, selector_location, timeout=None, selector_type=None):
        """
        等待指定的元素出现在页面中。

        参数:
        selector_location (str): 要等待的元素选择器。
        timeout (int, optional): 等待的最大时间(秒)。如果未提供,将使用默认超时时间。
        selector_type (str, optional): 选择器类型(例如 'css', 'xpath' 等)。

        无返回值。
        """
        wait = WebDriverWait(self.browser, timeout)
        if selector_type:
            selector_type = self.get_selector_type(selector_type)
        else:
            selector_type = self.get_selector_type(identify_selector_type(selector_location))
            selector_location = extract_value_from_selector(selector_location)
        wait.until(EC.presence_of_element_located((selector_type, selector_location)))

    # 获取定位类型
    def get_selector_type(self, selector_type):
        """
        将自定义的选择器类型映射为Selenium的选择器类型。

        参数:
        selector_type (str): 自定义的选择器类型(例如 'css', 'xpath' 等)。

        返回:
        by_type (selenium.webdriver.common.by.By): Selenium的选择器类型。
        """
        selector_type = selector_type.lower()
        if selector_type == ID:
            by_type = By.ID
        elif selector_type == XPATH:
            by_type = By.XPATH
        elif selector_type == LINK_TEXT:
            by_type = By.LINK_TEXT
        elif selector_type == PARTIAL_LINK_TEXT:
            by_type = By.PARTIAL_LINK_TEXT
        elif selector_type == NAME:
            by_type = By.NAME
        elif selector_type == TAG_NAME:
            by_type = By.TAG_NAME
        elif selector_type == CLASS_NAME:
            by_type = By.CLASS_NAME
        elif selector_type == CSS_SELECTOR:
            by_type = By.CSS_SELECTOR
        return by_type

    # 等待时间
    def wait_for_time(self, timeout):
        """
        异步等待指定的时间(秒)。

        参数:
        timeout (int): 等待的时间(秒)。

        无返回值。
        """
        time.sleep(timeout)

    # 查找多个元素
    def find_elements(self, selector_location, selector_type=None):
        # 传了selector_type就获取 没传就通过selector_location进行解析

        """
        查找多个元素。

        参数:
        selector_location (str): 要查找的元素选择器。
        selector_type (str, optional): 选择器类型(例如 'css', 'xpath' 等)。

        返回:
        elements (list): 包含匹配元素的列表。
        """
        if selector_type:
            selector_type = self.get_selector_type(selector_type)
        else:
            selector_type = self.get_selector_type(identify_selector_type(selector_location))
            selector_location = extract_value_from_selector(selector_location)
        return self.browser.find_elements(selector_type, selector_location)

    # 查找元素
    def find_element(self, selector_location, selector_type=None):
        """
        查找单个元素。

        参数:
        selector_location (str): 要查找的元素选择器。
        selector_type (str, optional): 选择器类型(例如 'css', 'xpath' 等)。

        返回:
        element (WebElement): 匹配的元素。
        """
        try:
            if selector_type:
                by_type = self.get_selector_type(selector_type)
            else:
                by_type = self.get_selector_type(identify_selector_type(selector_location))
                selector_location = extract_value_from_selector(selector_location)

            element = self.browser.find_element(by_type, selector_location)
            return element
        except NoSuchElementException:
            # 处理元素未找到的情况
            print(f"未找到匹配的元素: {selector_location}")
            return None  # 或者你可以选择抛出自定义的异常,或者返回其他默认值

    # 输入框 输入内容并提交
    def send_keys(self, selector_location, input_content, selector_type=None):
        """
        在指定的选择器位置输入文本内容。

        参数:
        selector_location (str): 要输入文本的元素选择器。
        input_content (str): 要输入的文本内容。
        selector_type (str, optional): 选择器类型(例如 'css', 'xpath' 等)。

        无返回值。
        """
        input_element = self.find_element(selector_location, selector_type)  # 查找输入框元素
        if input_element:
            input_element.send_keys(input_content)  # 输入文本内容
        else:
            print(f"未找到元素: {selector_location}")

    # 执行js命令
    def execute_script(self, script_command):
        """
        在当前页面上执行 JavaScript 脚本。

        参数:
        script_command (str): 要执行的 JavaScript 脚本命令。

        无返回值。
        """
        self.browser.execute_script(script_command)

    # 浏览器回退
    def go_back(self):
        """
        在浏览器中回退到上一个页面。

        无返回值。
        """
        self.browser.back()

    # 浏览器前进
    def go_forward(self):
        """
        在浏览器中执行前进操作,前往下一页。

        无返回值。
        """
        self.browser.forward()

    # 获取cookies
    def get_cookies(self):
        """
        获取当前页面的所有 Cookies。

        返回:
        cookies (List): 包含所有 Cookies 的列表。
        """
        return self.browser.get_cookies()

    # 添加cookies
    def add_cookie(self, cookie):
        """
        向当前页面添加一个 Cookie。

        参数:
        cookie (dict): 要添加的 Cookie 对象,应包含 'name' 和 'value' 属性。

        无返回值。
        """
        self.browser.add_cookie(cookie)

    # 删除cookies
    def del_cookies(self):
        """
        删除当前页面的所有 Cookies。

        无返回值。
        """
        self.browser.delete_all_cookies()

    # 切换选项卡
    def switch_tab(self, tab_index):
        """
        在浏览器窗口中切换到指定的标签页。

        参数:
        tab (int): 要切换到的标签页的索引号。

        无返回值。
        """
        self.browser.switch_to.window(self.browser.window_handles[tab_index])

    # 刷新页面
    def reload_page(self):
        """
        重新加载当前页面。

        无返回值。
        """
        self.browser.reload()

    # 截图
    def screen_page(self, file_path=None):
        """
        截取当前页面的屏幕截图并保存到指定路径。

        参数:
        file_path (str, optional): 保存截图的文件路径。如果未提供,将保存为默认文件名(当前目录下的'screenshot.png')。

        无返回值。
        """
        # 如果未提供文件路径,默认保存为'screenshot.png'在当前目录下
        if not file_path:
            file_path = 'screenshot.png'
        # 获取文件扩展名
        file_extension = os.path.splitext(file_path)[1][1:]
        # 如果不是png格式,转换成png
        if file_extension != 'png':
            file_path = os.path.splitext(file_path)[0] + '.png'

        # 截取屏幕截图并保存
        self.browser.save_screenshot(file_path)

    # 关闭浏览器
    def close_browser(self):
        """
        关闭浏览器。

        无返回值。
        """
        self.browser.close()

    def click(self, selector_location, selector_type=None):
        """
        在页面上点击指定的元素。

        参数:
        selector_location (str): 要点击的元素选择器。
        selector_type (str, optional): 选择器类型(例如 'css', 'xpath' 等)。

        无返回值。
        """
        element = self.find_element(selector_location, selector_type)  # 查找要点击的元素
        if element:
            element.click()  # 点击元素
        else:
            print(f"未找到元素: {selector_location}")

    # 拉拽动作
    def drag_and_drop(self, source_element, target_element):
        """
        在页面上执行拖拽动作。

        参数:
        source_element (WebElement): 要拖拽的源元素。
        target_element (WebElement): 拖拽的目标元素。

        无返回值。
        """
        actions = ActionChains(self.browser)  # 创建动作链对象
        actions.drag_and_drop(source_element, target_element)  # 执行拖拽操作
        actions.perform()  # 执行动作链中的所有动作
        self.browser.switch_to.alert.accept()  # 处理可能出现的弹窗(假设拖拽操作可能触发了弹窗)

    # iframe
    def to_iframe(self, frame):
        """
        切换到指定的 iframe。

        参数:
        frame (str or WebElement): 要切换的 iframe 元素或者 iframe 的名称或 ID。

        无返回值。
        """
        self.browser.switch_to.frame(frame)

    # 获取页面内容
    def get_content(self):
        """
        获取当前页面的内容。

        返回:
        content (str): 当前页面的 HTML 内容。
        """
        return self.browser.page_source


selenium_simulate = SeleniumSimulate()

其中用到的工具类如下文章来源地址https://www.toymoban.com/news/detail-773232.html

# 获取选择器属性
def identify_selector_type(selector):
    if re.match(r'^#[\w-]+$', selector):
        return 'id'
    elif re.match(r'^[.\w-]+[\w-]*$', selector):
        return 'css'
    elif re.match(r'^(//.*|\(//.*|\*\[contains\(.*\)\]|\*\[@id=\'.*\'\])', selector):
        return 'xpath'
    elif re.match(r'^<[\w-]+>$', selector):
        return 'tag'
    elif re.match(r'^<a.*>.*</a>$', selector):
        return 'link'
    elif re.match(r'.*<a.*>.*</a>.*', selector):
        return 'partial link'
    elif re.match(r'^\[name=[\'\"].*[\'\"]\]$', selector):
        return 'name'
    elif re.match(r'^\[class=[\'\"].*[\'\"]\]$', selector):
        return 'class'
    else:
        return 'unknown'


# 获取选择器内容
def extract_value_from_selector(selector):
    match = re.match(r'^#([\w-]+)$', selector)
    if match:
        return match.group(1)

    match = re.match(r'^\.([\w-]+[\w-]*)$', selector)
    if match:
        return match.group(1)

    match = re.match(r'^(//.*|\(//.*|\*\[contains\((.*)\)\]|\*\[@id=\'(.*)\'\])', selector)
    if match:
        return match.group(1)

    match = re.match(r'^<([\w-]+)>$', selector)
    if match:
        return match.group(1)

    match = re.match(r'^<a.*>(.*)</a>$', selector)
    if match:
        return match.group(1)

    match = re.match(r'.*<a.*>(.*)</a>.*', selector)
    if match:
        return match.group(1)

    match = re.match(r'^\[name=[\'\"](.*)[\'\"]\]$', selector)
    if match:
        return match.group(1)

    match = re.match(r'^\[class=[\'\"](.*)[\'\"]\]$', selector)
    if match:
        return match.group(1)

    return None

到了这里,关于【python爬虫】设计自己的爬虫 4. 封装模拟浏览器 Selenium的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Python爬虫入门:使用selenium库,webdriver库模拟浏览器爬虫,模拟用户爬虫,爬取网站内文章数据,循环爬取网站全部数据。

    Python爬虫入门:使用selenium库,webdriver库模拟浏览器爬虫,模拟用户爬虫,爬取网站内文章数据,循环爬取网站全部数据。

    *严正声明:本文仅限于技术讨论与分享,严禁用于非法途径。 目录 准备工具: 思路: 具体操作: 调用需要的库: 启动浏览器驱动: 代码主体:  完整代码(解析注释): Python环境; 安装selenium库; Python编辑器; 待爬取的网站; 安装好的浏览器; 与浏览器版本相对应的

    2023年04月24日
    浏览(41)
  • python爬虫进阶篇:Scrapy中使用Selenium模拟Firefox火狐浏览器爬取网页信息

    接着上一篇的笔记,Scrapy爬取普通无反爬、静态页面的网页时可以顺利爬取我们要的信息。但是大部分情况下我们要的数据所在的网页它是动态加载出来的(ajax请求后传回前端页面渲染、js调用function等)。这种情况下需要使用selenium进行模拟人工操作浏览器行为,实现自动化

    2024年02月04日
    浏览(46)
  • java爬虫遇到网页验证码怎么办?(使用selenium模拟浏览器并用python脚本解析验证码图片)

            笔者这几天在爬取数据的时候遇到了一个很闹心的问题,就是在我爬取数据的时候遇到了验证码,而这个验证码又是动态生成的,尝试了很多方法都没能绕开这个验证码问题。         我的解决方案是:使用selenium模拟浏览器行为,获取到动态生成的验证码后用

    2024年02月09日
    浏览(75)
  • 爬虫进阶之selenium模拟浏览器

    爬虫进阶之selenium模拟浏览器

    Selenium是一个用于自动化浏览器操作的工具,通常用于Web应用测试。然而,它也可以用作爬虫,通过模拟用户在浏览器中的操作来提取网页数据。以下是有关Selenium爬虫的一些基本介绍: 浏览器自动化: Selenium允许你通过编程方式控制浏览器的行为,包括打开网页、点击按钮

    2024年01月20日
    浏览(46)
  • [爬虫]2.2.1 使用Selenium库模拟浏览器操作

    [爬虫]2.2.1 使用Selenium库模拟浏览器操作

    Selenium是一个非常强大的工具,用于自动化Web浏览器的操作。它可以模拟真实用户的行为,如点击按钮,填写表单,滚动页面等。由于Selenium可以直接与浏览器交互,所以它可以处理那些需要JavaScript运行的动态网页。 首先,我们需要安装Selenium库。你可以使用pip命令来安装:

    2024年02月16日
    浏览(39)
  • python 爬虫热身篇 使用 requests 库通过 HTTP 读取网络数据,使用 pandas 读取网页上的表格,使用 Selenium 模拟浏览器操作

    python 爬虫热身篇 使用 requests 库通过 HTTP 读取网络数据,使用 pandas 读取网页上的表格,使用 Selenium 模拟浏览器操作

    在过去,收集数据是一项繁琐的工作,有时非常昂贵。机器学习项目不能没有数据。幸运的是,我们现在在网络上有很多数据可供我们使用。我们可以从 Web 复制数据来创建数据集。我们可以手动下载文件并将其保存到磁盘。但是,我们可以通过自动化数据收集来更有效地做

    2023年04月08日
    浏览(40)
  • 项目总面试技巧,利用Selenium模拟浏览器进行爬虫,解析底层原理

    项目总面试技巧,利用Selenium模拟浏览器进行爬虫,解析底层原理

    count = 0 def getCommentList(): global count try: commentList = driver.find_elements_by_css_selector(‘div.reply-content’) for comment in commentList: content = comment.find_element_by_tag_name(‘p’) print(content.text) count = count + 1 return commentList except: return None def clickMoreButton() - bool: try: moreButton = driver.find_element_by_css_se

    2024年04月17日
    浏览(14)
  • 阿里巴巴面试算法题利用Selenium模拟浏览器进行爬虫,【工作经验分享

    阿里巴巴面试算法题利用Selenium模拟浏览器进行爬虫,【工作经验分享

    def clickMoreButton() - bool: try: moreButton = driver.find_element_by_css_selector(‘button.page-last-btn’) moreButton.click() return True except: return False def main(): while True: try: driver.switch_to.frame(driver.find_element_by_css_selector(“iframe[title=‘livere-comment’]”)) except: pass commentList = getCommentList() waitTime = 0 while co

    2024年04月16日
    浏览(44)
  • 爬虫之Cookie获取:利用浏览器模拟一个cookie出来、面对反爬虫、加密的cookie的应对方法

    爬虫之Cookie获取:利用浏览器模拟一个cookie出来、面对反爬虫、加密的cookie的应对方法

    在爬虫或模拟请求时,特别是获取验证码的时候,反爬虫的网站的cookie或定期失效,复制出来使用是不行的 为了应对这种方式,我们可能就需要像浏览器打开网站一样,取得它信任的cookie selenium就是一个很好的手段 一、什么是selenium Selenium最初是一个自动化测试工具,Selen

    2024年01月16日
    浏览(11)
  • Python爬虫(2)-Selenium控制浏览器

    Python爬虫(2)-Selenium控制浏览器

    Selenium中提供了不少的方法来操作浏览器 使用driver.get(‘网址’)的方式来打开浏览器 driver.refresh() 浏览器切换标签的方法就是, driver.current_window_handle 用selenium点击新打开了一个网页,需要告知selenium目前这个窗口是新的窗口,那么它才能早新的页面进行操作不然的话就无法操

    2024年02月08日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包