首页 前端知识 Selenium Python 接口文档HTML版详解

Selenium Python 接口文档HTML版详解

2024-10-17 10:10:49 前端知识 前端哥 493 940 我要收藏

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Selenium是一个功能强大的自动化测试工具,支持Python等语言编写脚本,模拟用户在Web浏览器中的操作。通过本文深入探讨Selenium与Python结合使用的接口文档,读者将能更好地理解和运用这个工具。文章详细介绍Selenium WebDriver,Python中的Selenium库API,以及关键模块如webdriver、ActionChains、WebElement和Options。还包含元素定位、等待操作的方法和示例代码,帮助快速上手复杂的Web自动化测试。 selenium-python接口文档HTML版

1. Selenium概述与自动化测试

自动化测试简介

自动化测试是软件测试中一种提高效率的重要手段,通过运行预先编写好的测试脚本来模拟用户的操作行为,从而实现对应用的功能性、性能等各方面的测试。与手动测试相比,自动化测试能够大幅提高测试的速度和覆盖率,减少人力资源消耗,并确保测试过程的一致性和可重复性。

Selenium的兴起与发展

Selenium是一个在Web应用程序上进行自动化测试的工具,它可以模拟用户的各种操作,如点击按钮、填写表单、导航到不同页面等。Selenium迅速成为自动化测试领域中的标准工具之一,特别是在敏捷开发过程中,它能够有效地与持续集成系统集成,为快速反馈和迭代提供了支持。

Selenium与其他自动化测试工具比较

Selenium并非唯一可用的自动化测试工具,它与QTP (Quick Test Professional)、TestComplete等其他商业测试工具相比,具有开放源代码、跨平台、支持多种浏览器等显著优势。商业工具通常需要较高的初始投资,而Selenium的灵活性和易用性使其成为中小型企业及开源项目的首选。

通过以上内容,我们对自动化测试、Selenium的起源和发展以及与其他测试工具的比较有了初步了解。下一章将介绍如何在Python环境中结合使用Selenium进行自动化测试。

2. Python与Selenium结合使用

2.1 Python环境配置与安装Selenium

2.1.1 Python基础环境搭建

在开始学习如何使用Python与Selenium结合进行自动化测试之前,首先需要确保你的计算机上已经安装了Python环境。Python的安装过程非常简单,官方提供了适合各个操作系统的安装包。以下是安装Python的一般步骤:

  1. 访问Python官网下载页面(***)选择适合你操作系统的最新版本。
  2. 下载安装包后,双击运行,通常选择安装到默认路径,然后点击“下一步”。
  3. 在安装过程中,请确保勾选了“Add Python to PATH”选项,这样可以将Python添加到系统环境变量中,方便在命令行中直接调用Python。

安装完成后,你可以打开命令提示符或终端,输入 python --version 来验证Python是否正确安装。如果显示了版本号,则表示Python安装成功。

python --version

2.1.2 Selenium库安装与配置

Selenium是一个用于Web应用程序测试的工具,可以模拟用户在浏览器中的各种操作。Python环境中使用Selenium之前,需要安装对应的Python库。Selenium库可以通过pip(Python包管理工具)进行安装。在命令行中执行以下命令,即可完成Selenium库的安装:

pip install selenium

安装完成后,可以通过检查 selenium 包的版本来验证安装是否成功:

python -m pip show selenium

如果显示了版本信息,说明Selenium已经成功安装在你的Python环境中了。

2.2 Python脚本中Selenium的初始化

2.2.1 WebDriver的选择与初始化

在Python脚本中使用Selenium进行自动化测试时,首先需要初始化一个WebDriver对象。WebDriver负责与浏览器进行交云,通过模拟真实的用户操作来执行自动化测试脚本。Selenium支持多种浏览器,如Chrome、Firefox、Safari等。每种浏览器都对应一个具体的WebDriver。

以下是初始化Chrome WebDriver的示例代码:

from selenium import webdriver

# 设置ChromeDriver的路径,如果没有设置,则需要确保ChromeDriver在系统PATH中
chromedriver_path = '/path/to/chromedriver'

# 初始化WebDriver对象
driver = webdriver.Chrome(executable_path=chromedriver_path)

在上面的代码中, executable_path 参数指定了ChromeDriver的路径。如果没有指定,需要确保ChromeDriver已经添加到系统的PATH环境变量中。

2.2.2 页面加载和超时设置

在使用WebDriver时,页面加载和超时设置是经常会用到的配置。页面加载超时(page load timeout)是指在多少秒内页面应该完成加载,如果超时则会抛出异常。在某些情况下,页面可能需要较长时间加载,此时可以设置较长的超时时间。

以下是页面加载超时设置的示例代码:

from selenium import webdriver

# 初始化WebDriver
driver = webdriver.Chrome()

# 设置页面加载超时时间为30秒
driver.set_page_load_timeout(30)

# 访问一个网页
driver.get('***')

# 其他操作...

在上述代码中,使用 set_page_load_timeout 方法设置了页面加载超时时间为30秒。如果页面在30秒内没有加载完成,将会抛出一个 TimeoutException 异常。

超时设置不仅限于页面加载,还可以针对浏览器操作、元素查找等进行设置,以便更好地控制脚本的执行流程和响应异常情况。

总结

通过本章的内容,我们已经了解了如何配置Python环境,安装Selenium库,并在Python脚本中进行基本的WebDriver初始化和设置。下一章,我们将深入介绍WebDriver的具体操作,包括浏览器控制、页面导航等,以实现更复杂的自动化测试脚本。

3. WebDriver接口及浏览器交互

3.1 WebDriver基础操作

3.1.1 基本的浏览器控制命令

WebDriver提供了丰富的API来控制浏览器的行为。开发者可以利用这些API完成打开页面、刷新页面、后退和前进等操作。对于自动化测试人员来说,这些基础的控制命令是测试用例编写的基础。

首先,打开一个新的浏览器窗口可以使用 driver.get(url) 方法,其中 url 参数为要访问的网址。使用此命令时,WebDriver会打开指定的网址,并加载所有相关资源。

driver.get("***")

接下来,刷新当前页面可通过 driver.refresh() 实现。这个命令通常用于更新页面内容,尤其是在测试那些动态加载数据的网页时非常有用。

driver.refresh()

页面的后退和前进操作分别对应于浏览器的历史记录,使用 driver.back() driver.forward() 来实现。这对于测试页面链接和导航功能特别重要。

driver.back()   # 后退到上一个页面
driver.forward() # 前进到下一个页面

此外,结束浏览器会话可以使用 driver.quit() 命令,这将关闭所有窗口并退出浏览器。而 driver.close() 则只会关闭当前打开的窗口。

driver.quit()   # 关闭所有窗口并退出浏览器
driver.close()  # 关闭当前窗口

3.1.2 页面导航和窗口管理

页面导航是指在浏览器中访问不同的网页,而窗口管理则是对浏览器中打开的多个窗口进行管理。在WebDriver中,可以通过各种方法来实现这两项功能。

例如,要打开一个新的浏览器窗口,可以先使用 driver.execute_script() 执行一段JavaScript脚本,该脚本将创建一个新的窗口:

driver.execute_script("window.open();")

打开新窗口后,可以使用 driver.window_handles 获取当前所有窗口的句柄,并通过 driver.switch_to.window() 在不同窗口之间切换。这是管理多个窗口时非常重要的一个操作。

# 获取所有窗口句柄
windows = driver.window_handles
# 切换到最后一个窗口
driver.switch_to.window(windows[-1])

在页面导航方面,Selenium WebDriver支持使用 driver.get(url) 进行页面跳转。此外,还支持使用JavaScript脚本进行导航,这在某些特殊的测试场景下非常有用。

driver.execute_script("document.location.href = '***'")

以上提到的页面导航和窗口管理的API,允许自动化测试脚本模拟用户的浏览行为,并对测试的网页进行更细粒度的控制。

3.2 浏览器特定功能操作

不同浏览器有不同的特性, WebDriver为每种主流浏览器提供了特定的功能支持。例如,Selenium可以与ChromeDriver或GeckoDriver一起使用,分别支持Chrome和Firefox浏览器。在这小节中,我们探讨如何利用Selenium操作Chrome和Firefox的特定功能。

3.2.1 Chrome扩展和选项配置

在使用Chrome浏览器时,可以通过ChromeDriver安装Chrome扩展。这对于测试需要特定扩展支持的网页应用来说十分方便。首先需要下载对应的.crx文件,然后使用 ChromeOptions 类来加载它。

from selenium import webdriver

options = webdriver.ChromeOptions()
# 添加扩展
options.add_extension('path/to/extension.crx')
# 创建WebDriver实例
driver = webdriver.Chrome(options=options)

此外,还可以对Chrome进行更多高级配置,比如无头模式、特定用户代理、禁用沙盒模式等。通过这些配置,测试人员可以在不同的测试环境和场景下使用Chrome浏览器。

options = webdriver.ChromeOptions()
options.add_argument('--headless') # 启用无头模式
options.add_argument('user-agent=My User Agent 1.0')
driver = webdriver.Chrome(options=options)
3.2.2 Firefox配置文件和首选项设置

对于Firefox,Selenium提供了 FirefoxProfile 类来配置和优化浏览器设置。通过这种方式,可以为自动化测试设置特定的浏览器偏好设置,例如禁用更新检查、禁用安全警告等。

from selenium import webdriver

profile = webdriver.FirefoxProfile()
profile.set_preference("browser.startup.homepage", "about:blank")
profile.set_preference("startup.homepage_welcome_url", "about:blank")
profile.update_preferences()
# 使用配置好的profile创建Firefox实例
driver = webdriver.Firefox(firefox_profile=profile)

利用 FirefoxProfile ,测试人员能够对Firefox的行为进行精细控制,从而提供一个稳定且可预测的测试环境。

通过这些浏览器特定功能的配置和使用,Selenium可以更加灵活地进行自动化测试,适应不同的测试需求和场景。

在本节中,我们详细探讨了WebDriver基础操作和浏览器特定功能的使用方法。这为理解和运用Selenium WebDriver提供了坚实的基础,并将帮助自动化测试人员构建出更加强大和灵活的测试用例。

3.2 浏览器特定功能操作

3.2.1 Chrome扩展和选项配置

Chrome浏览器因其丰富的扩展插件生态而广受欢迎,通过使用Selenium,可以对Chrome浏览器进行扩展和特定选项配置,从而更好地满足自动化测试的需求。以下是如何在Selenium中操作Chrome扩展和选项配置的详细步骤和代码示例。

在自动化测试中,某些测试场景可能需要使用到特定的Chrome扩展,例如测试插件交互或者需要特定安全证书的网页等。使用 ChromeOptions 可以添加和管理Chrome扩展程序。

from selenium import webdriver

# 创建ChromeOptions实例
chrome_options = webdriver.ChromeOptions()

# 添加Chrome扩展,需要指定扩展文件路径
chrome_options.add_extension('path/to/your-extension.crx')

# 设置Chrome为无头模式(不显示GUI界面)
chrome_options.add_argument('--headless')

# 禁用信息栏提示
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])

# 设置偏好项,例如不自动检查更新
chrome_options.add_experimental_option('prefs', {
    'update': {
        'default': {
            'auto_update_enabled': False
        }
    }
})

# 使用配置的ChromeOptions创建WebDriver实例
driver = webdriver.Chrome(options=chrome_options)

在上述代码中,我们首先创建了一个 ChromeOptions 实例。然后,通过 add_extension 方法添加了一个Chrome扩展。接着,我们设置了Chrome的无头模式,这在服务器环境或者持续集成系统中非常有用。此外,我们还排除了默认的自动化提示和禁用了自动检查更新的偏好项。

3.2.2 Firefox配置文件和首选项设置

同样,Selenium也支持对Firefox浏览器进行详细的配置。通过 FirefoxProfile ,可以设置Firefox的启动页面、用户代理(User-Agent)、安全设置等。这对于创建一致性测试环境以及测试网站在不同条件下的表现是十分关键的。

from selenium import webdriver

# 创建FirefoxProfile实例
firefox_profile = webdriver.FirefoxProfile()

# 设置启动页面为空页面
firefox_profile.set_preference("browser.startup.homepage", "about:blank")

# 设置用户代理,可以模拟移动设备或者特定的浏览器版本
firefox_profile.set_preference("general.useragent.override", "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1")

# 禁用火狐安全警告
firefox_profile.set_preference("security.insecure_field_warning.contextual.enabled", False)

# 使用配置的FirefoxProfile创建WebDriver实例
driver = webdriver.Firefox(firefox_profile=firefox_profile)

在上面的代码中,首先我们创建了 FirefoxProfile 的实例。然后,我们设置了启动页面为一个空白页面,并且覆盖了默认的用户代理,模拟了一个iPhone设备。此外,我们还禁用了一些安全警告,这在测试网站不安全的输入处理时是有用的。

通过这些配置,测试人员能够模拟各种特定环境下的浏览器行为,为自动化测试提供了一个更加稳定和可控的平台。本小节介绍了如何使用Selenium针对不同浏览器进行个性化配置,以满足特定的测试需求。这不仅提高了测试的精确度,也扩展了测试人员的能力边界,使得他们能够更灵活地应对复杂多变的测试场景。

在本节中,我们详细探讨了如何在Selenium中进行浏览器特定功能的配置操作。这些操作对自动化测试场景提供了强有力的支持,尤其是模拟用户真实行为和验证特定浏览器环境下的网站功能。这些技能的掌握将大大增强自动化测试的效果和覆盖面。

4. Selenium库API介绍

4.1 常用的Selenium库API

4.1.1 元素查找与基本交互

元素查找是自动化测试中最常见的任务之一,Selenium提供了多种定位元素的方法。其中, find_element_by_id find_element_by_name find_element_by_class_name find_element_by_xpath find_element_by_css_selector 是最基础的几种定位方法。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('***')

# 通过ID查找元素
element_by_id = driver.find_element_by_id('unique-element-id')

# 通过Name属性查找元素
element_by_name = driver.find_element_by_name('username')

# 通过CSS选择器查找元素
element_by_css = driver.find_element_by_css_selector('.container .header')

# 通过XPath查找元素
element_by_xpath = driver.find_element_by_xpath('//div[@id="unique-element-id"]')

# 关闭浏览器
driver.quit()

每个API的参数说明: - find_element_by_id : 通过元素的ID属性进行查找。 - find_element_by_name : 通过元素的Name属性进行查找。 - find_element_by_class_name : 通过元素的Class属性进行查找,需要注意的是,此方法返回的是第一个匹配的元素,如果页面上有多个具有相同Class名的元素,只返回第一个。 - find_element_by_xpath : 通过XPath表达式进行查找,这是一种非常强大且灵活的元素定位方法。 - find_element_by_css_selector : 通过CSS选择器进行查找,其语法类似于CSS。

逻辑分析: 在使用Selenium时,通常需要确保元素已经加载在DOM中,并且可见,才能进行交互操作。如果页面元素还未加载完成,直接操作可能会引发异常。因此,有时候需要配合等待机制(如隐式等待和显式等待)来确保元素的可见性。

4.1.2 表单操作和多窗口处理

在自动化测试过程中,常常需要处理各种表单元素,如输入框、复选框、单选按钮和下拉列表等。Selenium库同样提供了丰富的API来进行这些操作。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('***')

# 填写登录表单
driver.find_element_by_id('username').send_keys('testuser')
driver.find_element_by_id('password').send_keys('testpass')
driver.find_element_by_id('login-button').click()

# 切换到弹出的窗口
windows = driver.window_handles
driver.switch_to.window(windows[-1])

# 填写另一个表单
driver.find_element_by_name('email').send_keys('***')
driver.find_element_by_name('submit').click()

# 返回主窗口并关闭
driver.switch_to.window(windows[0])
driver.quit()

在这段代码中,我们首先打开了一个网页,并执行了登录操作。之后,代码切换到了弹出的新窗口,并进行了其他操作。最后,我们切换回主窗口并关闭了浏览器。

逻辑分析: - send_keys() 方法用于输入文本到输入框等可编辑元素。 - click() 方法模拟鼠标点击操作,可以触发按钮或链接。 - driver.window_handles 获取当前会话中所有窗口的句柄。 - driver.switch_to.window() 方法用于切换当前焦点窗口。

在处理多窗口场景时,窗口句柄是识别不同窗口的唯一标识,确保我们能够准确地在多个窗口之间切换,完成测试任务。

5. 定位页面元素的方法

在自动化测试过程中,定位页面元素是一个至关重要且频繁执行的操作。通过定位页面元素,自动化脚本可以与网页上的不同组件交互,执行诸如点击按钮、填写表单等操作。若不能正确地定位到页面元素,后续的测试步骤将无法进行。因此,本章节将重点讲解几种常用的页面元素定位方法,并介绍一些定位策略和技巧,以帮助读者更高效地进行自动化测试。

5.1 元素定位基础

5.1.1 ID、Name定位方法

使用元素的ID或Name属性进行定位是最简单也是最直接的方法之一。在HTML中,每个元素都可以通过ID或Name属性进行唯一标识,Selenium提供了相应的方法来支持这种定位方式。

  • 使用ID定位

ID定位利用 find_element_by_id 方法,通过传递一个元素的ID属性值来查找对应的页面元素。在实际操作中,该方法返回页面上第一个匹配指定ID的元素。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('***')
element = driver.find_element_by_id('myid')

在上述代码中,我们首先初始化了一个WebDriver对象,并导航至目标网页。接着使用 find_element_by_id 方法定位ID为 myid 的元素,并将其存储在变量 element 中。

  • 使用Name定位

Name定位使用 find_element_by_name 方法,通过元素的Name属性值来进行定位。该方法返回页面上第一个匹配指定Name属性值的元素。

element = driver.find_element_by_name('username')

在这段代码中,我们通过元素的Name属性值 username 来查找对应的表单输入框。

5.1.2 CSS选择器和XPath定位方法

当ID或Name属性不可用,或者为了更灵活地选择元素时,我们通常会使用CSS选择器或XPath来定位页面元素。

  • 使用CSS选择器定位

CSS选择器允许我们通过元素的类、ID、标签名、属性等信息来选择页面元素。Selenium提供了 find_element_by_css_selector 方法来使用CSS选择器进行元素定位。

element = driver.find_element_by_css_selector('#myid')
element = driver.find_element_by_css_selector('input[name="username"]')

在第一个例子中,我们通过ID来定位页面元素。在第二个例子中,我们通过表单输入框的Name属性来选择元素。

  • 使用XPath定位

XPath是另一种强大的XML路径表达式语言,Selenium通过 find_element_by_xpath 方法提供了对XPath的支持。XPath允许我们使用复杂的路径表达式来定位页面元素,使得定位操作更为灵活。

element = driver.find_element_by_xpath('//input[@id="myid"]')
element = driver.find_element_by_xpath("//input[@name='username']")

在这两个例子中,我们分别使用了属性选择器来查找具有特定ID或Name的输入框元素。

5.2 定位策略与技巧

5.2.1 链式定位和分组定位

  • 链式定位

链式定位是一种通过连续调用定位方法来逐层缩小查找范围的技巧。通过链式定位,我们可以构建出一个从页面根元素到目标元素的定位链。

element = driver.find_element_by_xpath('//div[@class="container"]/form/input')

上述代码中,我们通过XPath链式表达式首先定位到class为 container div 元素,然后继续定位其内部的 form 元素,最终找到该表单内的 input 元素。

  • 分组定位

分组定位是将多个元素定位方法组合起来进行一次性的定位。这通常用在需要定位多个具有相似结构的元素时。

elements = driver.find_elements_by_xpath('//div[@class="items"]/div')

在此例中,我们一次性获取了所有 class 属性为 items div 元素下的所有子 div 元素。

5.2.2 隐式等待和显式等待的使用

  • 隐式等待

隐式等待是一种告诉WebDriver等待一定时间直到元素出现的策略,而不是立即抛出 NoSuchElementException 异常。在Python中,可以通过 implicitly_wait 方法来设置。

driver.implicitly_wait(10) # 设置最长等待时间为10秒

在这个例子中,当调用 find_element_by_* 方法查找元素时,如果元素在10秒内没有找到,就会抛出异常。如果在指定时间内找到了元素,则继续执行后续代码。

  • 显式等待

显式等待提供了更加灵活的方式来等待某个条件成立。它允许在等待过程中执行检查条件的自定义函数,直到某个条件成立或者等待超时。

``` mon.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC

element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, 'myid')) )


上述代码中,我们设置了一个最多等待10秒的显式等待。`until`方法会检查传入的条件是否在指定时间内成立。这里使用`presence_of_element_located`条件检查ID为`myid`的元素是否已经出现在DOM中。

在本章节中,我们详细介绍了页面元素定位的基本方法和策略,包括使用ID、Name、CSS选择器、XPath进行元素定位,以及通过链式定位、分组定位、隐式等待和显式等待来提升自动化测试的效率和可靠性。这些知识构成了自动化测试中与页面元素交互的基础,也是进行复杂测试场景编写的基石。通过本章节的介绍,读者应该能够熟练地在实际项目中应用这些定位方法,并根据实际情况选择合适的定位策略。

# 6. 等待操作的实现

等待操作是自动化测试中重要的概念,它能够确保在执行操作前页面已经加载完成需要的元素,从而避免因页面加载延迟导致的测试失败。等待操作分为显式等待和隐式等待,下面我们将详细讨论这两种等待操作的实现方式及其在实践中的应用。

## 6.1 等待操作的必要性与分类

在进行Web自动化测试时,由于网络延迟、服务器响应时间等因素,页面加载速度并不总是一致的。这就要求我们在脚本中引入等待机制,来确保元素的加载和渲染。

### 6.1.1 隐式等待与显式等待的概念

- **隐式等待**:设置一个全局的等待时间,如果在指定时间内没有找到元素,则抛出异常。
- **显式等待**:对某个条件进行检查,如果在指定时间内条件成立,则继续执行;否则抛出超时异常。

### 6.1.2 强制等待与可配置等待

- **强制等待**:简单粗暴地让脚本暂停执行一段时间,不建议使用,因为它不考虑页面的实际加载情况。
- **可配置等待**:显式等待提供了更灵活的等待条件,可以根据实际情况来调整等待条件。

## 6.2 实际应用中的等待技巧

在编写自动化测试脚本时,如何恰当地使用等待操作是提高测试稳定性的关键。

### 6.2.1 等待条件的编写方法

示例代码(Python使用Selenium):

```***
***mon.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get('***')

try:
    # 显式等待
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "example"))
    )
    print(element.text)

    # 隐式等待
    driver.implicitly_wait(10)
    element = driver.find_element(By.ID, "example")
    print(element.text)

finally:
    driver.quit()

6.2.2 异常处理与等待策略调整

在实际应用中,需要对等待操作中的各种异常进行处理,以及根据测试结果调整等待策略:

  • 异常处理 :例如,页面元素长时间未加载成功时,我们需要处理超时异常,并记录失败信息。
  • 等待策略调整 :如果某个元素频繁出现加载超时问题,则可能需要调整显式等待中的条件,或者增加隐式等待的时间。

通过上述等待操作的实现和实际应用技巧,可以有效地提升自动化测试脚本的稳定性和可靠性。在后续章节中,我们将深入探讨HTML版接口文档的创建和维护,以及通过示例代码展示如何将这些理论知识应用于实际的自动化测试实践中。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Selenium是一个功能强大的自动化测试工具,支持Python等语言编写脚本,模拟用户在Web浏览器中的操作。通过本文深入探讨Selenium与Python结合使用的接口文档,读者将能更好地理解和运用这个工具。文章详细介绍Selenium WebDriver,Python中的Selenium库API,以及关键模块如webdriver、ActionChains、WebElement和Options。还包含元素定位、等待操作的方法和示例代码,帮助快速上手复杂的Web自动化测试。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

转载请注明出处或者链接地址:https://www.qianduange.cn//article/19047.html
标签
评论
发布的文章
大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!