selenium基础学习笔记&淘宝商品爬取

selenium 介绍

selenium是web脚本测试工具,在爬虫中也可以利用它来模拟真人操作,在一些防爬机制比较严格的网页爬虫中十分有效,它的优势在于能模拟真人操作,处理动态渲染网页、验证码等情况,缺点在于效率较低。

本文写作流程

在这里插入图片描述
声明 笔者水平有限,有错误欢迎指出。笔者也借此记录selenium学习的过程,以便后续复习。

1.1 安装selenium库

conda install selenium

1.2 selenium常用类

selenium官方技术文档
selenium官方技术文档
①webdriver类主要方法和属性
②BY类
③WebElement类的方法及属性
④Wait类
⑤expected_conditions (EC)类
⑥TimeoutException 类

1.2.1webdriver类主要方法和属性

1、库导入
from selenium.webdriver import webdriver
2、实例化webdriver 类
driver = webdriver.Edge()

可选的浏览器
.Edge()
.Chrom()

3、driver 对象的方法及属性
driver.get(url)
driver.exit()
diver.find_element(BY.  ,   "   ")               #返回一个WebElement
driver.find_elements(BY.    ,  "   ")			#返回由WebElement 组成的列表

driver.title

1.2.2 By类

用于定位页面元素,作为dircer.find_element()的参数

1、库导入
from selenium.webdriver.common.by import By
2、定位策略

By 类提供了多种定位策略,可以根据元素的不同属性来选择最合适的策略。这些策略包括:

ID:通过元素的 id 属性定位。
Name:通过元素的 name 属性定位。
Class Name:通过元素的 class 属性定位。
Tag Name:通过元素的标签名定位(如 div, span)。
CSS Selector:通过 CSS 选择器定位。
CSS选择器解释链接
XPath:通过 XPath 表达式定位。

3、使用不同的 By 方法定位元素
    # 通过 ID 定位
    element_by_id = driver.find_element(By.ID, 'element_id')
    
    # 通过 Name 定位
    element_by_name = driver.find_element(By.NAME, 'element_name')
    
    # 通过 Class Name 定位
    element_by_class_name = driver.find_element(By.CLASS_NAME, 'element_class')
    
    # 通过 Tag Name 定位
    element_by_tag_name = driver.find_element(By.TAG_NAME, 'div')
    
    # 通过 CSS Selector 定位
    element_by_css_selector = driver.find_element(By.CSS_SELECTOR, '.class_name #element_id')
    
    # 通过 XPath 定位
    element_by_xpath = driver.find_element(By.XPATH, '//div[@id="element_id"]')

By类作为EC.element_to_be_clickable()的参数时,(by, value)作为元组传入

#示例代码
next_page_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '//button/span[contains(text(),"下一页")]')))

1.2.3 WebElement对象的方法及属性**

WebElement对象一般是某个页面元素

1、WebElement对象常用方法
click()
# 模拟点击元素的操作。
element.click()

send_keys(*value)
# 向元素发送键盘输入。特殊的输入包含在Keys类中,包括RETURN、ALT等
element.send_keys("text to input")

clear()
# 清除元素中的内容(通常用于输入框)。
element.clear()

submit()
# 提交表单。如果元素位于表单内,则提交该表单。
element.submit()

get_attribute(name)
# 获取元素的属性值。
attribute_value = element.get_attribute("attribute_name")

get_property(name)
# 获取元素的属性值。与 get_attribute 类似,但更倾向于 JavaScript 属性。
property_value = element.get_property("property_name")

get_css_value(property_name)
# 获取元素的 CSS 样式属性值。
css_value = element.get_css_value("property_name")

is_displayed()
# 检查元素是否在页面上可见。
is_visible = element.is_displayed()

is_enabled()
# 检查元素是否可用。
is_enabled = element.is_enabled()

is_selected()
# 检查元素是否被选中(适用于复选框、单选按钮等)。
is_selected = element.is_selected()

find_element(by, value)
# 在当前元素内查找子元素。
child_element = element.find_element(By.CSS_SELECTOR, "selector")

1.2.4 wait类

等待类用于实现显式等待,直到某个条件发生为止。Selenium 提供了 WebDriverWait 和条件类 expected_conditions。

以下转载

3.5.1 元素级等待机制——强制等待
利用time模块中的time.sleep()来实现,这种做法的弊端很明,处理起来毫无弹性。执行的速度和机器的性能有关,如果有一台机器严重卡顿,登录面板有可能 3s 都弹不出来

import time 
time.sleep(5)

3.5.2 元素级等待机制——隐式等待

webdriver.implicitly_wait(等待秒数) 

是在执行 find_element()/find_elements()这类函数时,如果在规定的时间内找到元素那么将立即结束等待,否则会一直等待,如果超过时间元素还未出现就会抛出找不到元素的异常
案例演示

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.implicitly_wait(10)	# 设置的最长隐式等待时间为 10s
driver.get("https://www.baidu.com")
driver.find_element(By.LINK_TEXT, "登录").click()
driver.find_element(By.LINK_TEXT, "立即注册").click()

在这个案例中虽然设置的最长隐式等待时间为 10s,但由于通常 1s 内登录面板就会弹出,因此 Selenium 检测到元素已经存在就会结束等待立即执行下一行代码

注:隐式等待是全局设置的,一旦设置会在整个WebDriver实例的生命周期内生效

3.5.3 元素级等待机制——显示等待
元素级等待的最佳实践方式是显示等待,显示等待机制只需要指定条件判断函数,Selenium会每隔一定的时间检测该条件是否成立,如果成立就立刻执行下一步,否则一直等待,直到超过最大等待时间抛出超时异常

from selenium.webdriver.support.wait import WebDriverWait 

WebDriverWait 的实例化方法如下
WebDriverWait(WebDriver实例, 超时秒数, 检测时间间隔[可选], 可忽略异常集合[可选] )
‘’’
可选参数1:检测时间间隔:调用 until 或 until_not 传入的条件判断函数的间隔时间,默认为 0.5s
可选参数2:可忽略异常集合:在调用 until 或 until_not 中传入的条件判断函数时,如果抛出的是这个集合中定义的异常,代码就不会执行失败,会继续正常执行
‘’’

实例化 WebDriverWait 对象后,可以调用 WebDriverWait 对象的以下两个函数来执行等待,等待直到条件判断函数的返回值不为 False

WebDriverWait.until(条件判断函数, “超时后的自定义异常消息”[可选])
WebDriverWait.until_not(条件判断函数, “超时后的自定义异常消息”[可选])

# 等待元素可见
wait = WebDriverWait(driver, 10)
element = wait.until(EC.visibility_of_element_located((By.ID, 'element_id')))

————————————————

                        版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接

1.2.4 expected_conditions (EC)类

该类包含了许多条件,用于在显式等待中判断条件是否满足。

1、库导入
from selenium.webdriver.support import expected_conditions as EC
2、常用方法
# 等待元素可点击
element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'element_id')))
......

1.2.5 TimeoutException 类

是 Selenium 中用于处理超时情况的异常类。它通常在等待某个条件满足或某个元素加载时出现,当超时时间到达而条件未满足时会抛出该异常。TimeoutException 是一个继承自 WebDriverException 的类。

1、导入 TimeoutException 类

要在代码中处理 TimeoutException,首先需要从 selenium.common.exceptions 导入

from selenium.common.exceptions import TimeoutException
2、什么时候会抛出 TimeoutException

显式等待超时:当使用显式等待 (WebDriverWait) 等待某个条件时,如果在规定的时间内条件没有满足,就会抛出 TimeoutException。
页面加载超时:如果设置了页面加载超时时间,而页面没有在规定时间内加载完毕,也会抛出该异常。

3、示例
try:
    # 使用显式等待等待元素加载,最长等待时间为10秒
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, 'example_element_id'))
    )
    print(element.text)
except TimeoutException:
    print("超时异常:元素未在规定时间内加载")
finally:
    # 关闭浏览器
    driver.quit()

2、下载浏览器对应驱动并设置系统路径

浏览器驱动的下载在此省略,自行浏览器搜索相关博客。

有遇到的报错

selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for MicrosoftEdge

最终解决的方法是重新在环境变量中设置了Path,我原来设的Path变量只设到了msedgedriver.exe所在的文件夹,后来加到了msedgedriver.exe的位置。

#原来的
#D:\
#后来的
#D:\msedgedriver.exe

3、CMD端打开浏览器并设置端口

大致步骤,管理员运行打开CMD

cd C:\Program Files (x86)\Microsoft\Edge\Application
msedge.exe --remote-debugging-port=9222 --user-data-dir="D:\AutoEdge"
#这里的AutoEdge文件用于存放浏览器产生的数据

遇到的报错

WebDriverException: Message: no such execution context: frame does not have execution context

后来搜索这个ERROR,原来是第一次cmd端打开Edge浏览器时设置的用户数据文件不能有其它东西,要建一个空的文件夹。

msedge.exe --remote-debugging-port=9222 --user-data-dir="D:\AutoEdge"
#这里第一次运行这句代码时,AutoEdge得是一个空的文件夹。

Edge浏览器端口接法教程
传送门

4、seleniuim接管浏览器&爬虫

爬取思路参考https://blog.csdn.net/fullbug/article/details/136296522

链接中案例基于Chrom浏览器,但我想使用Edge浏览器,selenium3对Chrom浏览器和Edge浏览器的webdriver对象的options参数是不一样的,所以我的接口在CMD端写好后,还得弄明白Edge浏览器的options参数怎么写。

找到了这篇文档,记录了EdgeOptions()对象的使用。linkhttps://www.cnblogs.com/fanghsiu/p/15838879.html
但我还是不明白怎么添加port参数和日志文件地址参数。

查看了selenium官方文档
https://github.com/SeleniumHQ/seleniumhq.github.io/blob/trunk/examples/python/tests/browsers/test_edge.py
在初始化Edge浏览器这步,遇到了很多报错,最终实现时的代码如下

from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options

# 指定 msedgedriver 的路径
driver_path = "D:\msedgedriver.exe"  # 请替换为实际的 msedgedriver 路径

# 初始化浏览器
options = Options()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
service = Service(executable_path=driver_path)
driver = webdriver.Edge(service=service, options=options)
遇到的报错

在代码中,当我想将executable_path=driver_path直接作为webdriver.Edge()的参数时,也遇到了报错,报错信息提示没有executable这个参数,后来在ChatGPT的帮助下通过Service类添加。代码如上。

已成功爬取,附上完整代码

from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException, NoSuchWindowException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from urllib.parse import quote
from pyquery import PyQuery as pq
import time

# 指定 msedgedriver 的路径
driver_path = "D:\msedgedriver.exe"  # 请替换为实际的 msedgedriver 路径

# 初始化浏览器
options = Options()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
service = Service(executable_path=driver_path)

try:
    driver = webdriver.Edge(service=service, options=options)
except Exception as e:
    print(f"初始化 WebDriver 时发生错误: {e}")
    raise

wait = WebDriverWait(driver, 240)


def login_taobao():
    try:
        login_url = 'https://login.taobao.com//member//login.jhtml'
        driver.get(login_url)
        # input_login_id = wait.until(EC.presence_of_element_located((By.NAME, "fm-login-id")))
        # input_login_passward = wait.until(EC.presence_of_element_located((By.NAME, "fm-login-password")))
        # input_login_id.send_keys("")# *************************添加自己的账号
        # input_login_passward.send_keys("") #***************添加自己的密码
        # submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.fm-button.fm-submit.password-login')))
        # submit.click()
        is_login = wait.until(EC.url_changes(login_url))
        return is_login
    except TimeoutException:
        print("TimeoutException")
        # submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.fm-button.fm-submit.password-login')))
        # submit.click()
        is_login = wait.until(EC.url_changes(login_url))
        if is_login:
            return is_login
        else:
            login_taobao()


def get_products(products):
    try:
        html = driver.page_source
        doc = pq(html)
        items = doc('.Card--doubleCardWrapper--L2XFE73').items()
        for item in items:
            p = {
                'url': item.attr('herf'),
                'price': item.find('.Price--priceInt--ZlsSi_M').text() + item.find(
                    ".Price--priceFloat--h2RR0RK").text(),
                'title': item.find('.Title--title--jCOPvpf').text(),
                'shop': item.find(".ShopInfo--shopName--rg6mGmy").text(),
                'salenum': item.find('.Price--realSales--FhTZc7U').text()}
            print(p)

            products.append(p)
    except:
        print("-----get_products_ERROR-------")


def Index_page(url, cur_page, max_page, products):
    try:
        driver.get(url)
        get_products(products)
        time.sleep(5)
        next_page_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '//button/span[contains(text(),"下一页")]')))
        next_page_btn.click()
        change = wait.until(EC.url_changes(url))
        if change and cur_page < max_page:
            url = driver.current_url
            cur_page = cur_page + 1
            Index_page(url, cur_page, max_page, products)

    except TimeoutException:
        print('--------Index_page() TimeoutException----------')


def main():
    is_login = login_taobao()
    if is_login:
        KEYWORD = "植物"
        url = "https://s.taobao.com//search?area=c2c&commend=all&page=1&q=" + quote(KEYWORD) + "&tab=all"
        max_page = 10
        products = []
        Index_page(url, 1, max_page, products)
    else:
        print('登录失败')


main()

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值