【Python爬虫】Selenium使用

安装配置教程自行搜索

所用驱动chromedriver应与chrome浏览器版本相对应

pip install selenium

笔者selenium所用版本为4.11.2,新旧版之间会有差别

from selenium import webdriver
driver = webdriver.Chrome()

实例化driver对象后,driver对象有一些常用的属性和方法

driver.page_source #当前标签页浏览器渲染之后的网页源代码
driver.current_url #当前标签页的url
driver.close()     #关闭当前标签页,如果只有一个标签页则关闭整个浏览器
driver.quit()      #关闭浏览器
driver.forward()   #页面前进
driver.back()      #页面后退
driver.refrash()   #页面刷新
driver.save_screenshot("img_name") #页面截图

我们使用Selenium时会觉得浏览器加载很慢,这和它的页面加载策略有关

Selenium的页面加载策略(pageLoadStrategy)

本段摘自:https://blog.csdn.net/momoda118/article/details/120624777

  1. normal:等待整个页面加载完毕再开始执行操作(默认为此)
  2. eager:等待整个dom树加载完成,即DOMContentLoaded这个事件完成,也就是只要 HTML完全加载和解析完毕就开始执行操作。放弃等待图片、样式、子帧的加载。
  3. none:等待html下载完成,哪怕还没开始解析就开始执行操作。

加载策略设置为eager

配置代码如下:

chrome_options = Options()
chrome_options.page_load_strategy = 'eager'
driver = webdriver.Chrome(options=chrome_options)

加载策略设置为none

加载策略设置为none,并引入retry做重试(目的是为了防止报错,当然设置隐式等待也可,但没retry稳妥)可以只用2s左右就能执行完成,完整代码如下:

import datetime
from retrying import retry  # 需第三方库,需pip进行安装
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By

@retry(wait_fixed=10, stop_max_attempt_number=1)
def click(path):
    driver.find_element(By.XPATH, path).click()
    
chrome_options = Options()
chrome_options.page_load_strategy = 'none'
driver = webdriver.Chrome(options=chrome_options)
start_time = datetime.datetime.now()
driver.get('https://www.iqiyi.com/')
click('//*[@id="block-C"]/div/div/div/div[1]/div[1]/div/div[1]/div/div/a/span[2]')
end_time = datetime.datetime.now()
print(end_time - start_time)

元素定位

本段参考:https://blog.csdn.net/qq_18298049/article/details/117136214

element = driver.find_element(By.ID, 'kw')   # 通过ID定位搜索框

element = driver.find_element(By.NAME, 'wd')   # 通过name定位搜索框

element = driver.find_element(By.CLASS_NAME, 's_ipt')   # 获取百度首页搜索框

element = driver.find_element(By.TAG_NAME, 'input')  # 查找标签名称是input的元素

element = driver.find_element(By.LINK_TEXT, '贴吧')   # 定位贴吧

element = driver.find_element(By.PARTIAL_LINK_TEXT, '贴')   # 定位贴吧

头尾匹配写法:其中,头尾匹配可以是部分字符,部分匹配需要是按空格分隔的完整字符。

条件htmlvalues 写法1 (头部匹配)values 写法2 (尾部匹配)values 写法3 (部分匹配)
class< button class=“el-button el-button–primary”>‘[class^=“el-button”]’‘[class$=“–primary”]’‘[class~=“el-button”]’

css selector

element = driver.find_element(By.CSS_SELECTOR, '#kw')   # #kw id选择器
element = driver.find_element(By.CSS_SELECTOR, '.s_ipt')   # .s_ipt class选择器
element = driver.find_element(By.CSS_SELECTOR, 'form #kw')   # 后代元素选择器
element = driver.find_element(By.CSS_SELECTOR, "input[name='wd']")   # 属性值定位选择器

# 同时包含两个条件
# 包含type='text'与maxlength='50'两个条件的元素,语法上不需要and进行连接
driver.find_element(By.CSS_SELECTOR, '[type="text"][maxlength="50"]')
# 包含一个条件且不包含另一条件
# 包含type='text'且不包含maxlength='50'的元素,语法上使用:not()进行连接
driver.find_element(By.CSS_SELECTOR, '[type="text"]:not([maxlength="50"])')

xpath

相对路径

// #查找页面根元素
//input #查找页面上所有的input元素
//form[1]/input #查找页面上第一个form元素内的直接子input元素(即只包括form元素的下一级input元素,使用绝对路径表示,单/号)
//form[1]//input #查找页面上第一个form元素内的所有子input元素(只要在form元素内的input都算,不管还嵌套了多少个其他标签,使用相对路径表示,双//号)
//form[1] #查找页面上第一个form元素
//form[@id='loginForm'] #查找页面上id为loginForm的form元素
//input[@name='username'] #查找页面上具有name属性为username的input元素
//form[@id='loginForm']/input[1] #查找页面上id为loginForm的form元素下的第一个input元素
//input[@name='continue'][@type='button'] #查找页面具有name属性为contiune并且type属性为button的input元素
//form[@id='loginForm']/input[4] #查找页面上id为loginForm的form元素下第4个input元素

写法为:element = driver.find_element(By.XPATH, '路径')

绝对路径

调试模式找到元素右键复制

不建议写绝对路径!!!

定位模糊匹配

contains关键字://a[contains(@href, ‘logout’)]

寻找页面中href属性值包含有logout这个单词的所有a元素

start-with关键字://a[starts-with(@name, ‘start)])

寻找name属性以start开头的a元素。其中@后面的name可以替换成元素的任意其他属性

text关键字://*[text()=’确定’]

一个简单粗暴的定位方式,无需知道属于什么标签元素,常用于纯文字查找,也可用于链接元素文本查找

//a[contains(text(), ’退出’)]

用于知道超链接上显示的部分或全部文本信息时

find_element和find_elements

  • find_element返回匹配到的第一个标签对象;find_elements返回列表
  • find_element匹配不到抛出异常;find_elements匹配不到返回空列表

元素操作

示例1:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time

chrome_options = Options()
chrome_options.page_load_strategy = 'eager'
service = Service('chromedriver.exe路径')

driver = webdriver.Chrome(service=service, options=chrome_options)
driver.get("https://www.baidu.com")
driver.find_element(By.ID, 'kw').send_keys('python')
driver.find_element(By.ID, 'su').click()
time.sleep(5)
driver.close()

示例2:

el_list: list = driver.find_elements(By.XPATH, "/html/body/div[6]/div[2]/ul/li/div[2]/h2/a")
for el in el_list:
    print(el.text)
    print(el.get_attribute('href'))

标签页(窗口)切换

我们在使用浏览器的时候,会自动转到新的标签页,但selenium不会这样,我们需要进行操作来实现

利用窗口句柄切(指向标签页对象的标识)换到句柄指向的标签页

driver.get("url")
time.sleep(3)
print(driver.current_url) #获取当前页面的url
print(driver.window_handles) #获取当前所有存在的窗口句柄,多个句柄以列表方式存储
driver.find_element(By.XPATH, "/html/body/div[6]/div[2]/ul/li[1]/div[2]/h2").click()
print(driver.current_url)
print(driver.window_handles)
time.sleep(3)
driver.switch_to.window(driver.window_handles[-1]) #切换至新窗口
print(driver.current_url)
time.sleep(3)
driver.close() #关闭当前窗口
driver.switch_to.window(driver.window_handles[0]) #切换至原窗口
print(driver.current_url)

iframe切换

<iframe src="1.html" id="hogwarts_id" name="hogwarts_name"></iframe>

实现:

# index:传入整型的参数,从 0 开始,这里的 0 就是第一个 frame
driver.switch_to.frame(0)
#id:iframe 的 id
driver.switch_to.frame("hogwarts_id")
#name: iframe 的 name
driver.switch_to.frame("hogwarts_name")
#WebElement: 传入 `selenium.webelement` 对象
driver.switch_to.frame(driver.find_element(By.TAG_NAME,"iframe"))

在切换页面之后,如果还想操作原页面,则可以使用:

driver.switch_to.default_content()

嵌套多层iframe的切换:

<html>
    <iframe src="a.html" id="frame1">
    	    <iframe src="b.html" id="frame2" >
    			<input id="kw" / >
			</iframe>
    </iframe>
</html>

多层嵌套的情况下,如果要从主界面切换到第二层iframe,则需要一层一层的切换进去,即先切换到frame1,再切换到frame2,而不是直接切换进入frame2

driver.switch_to.frame("frame1")
driver.switch_to.frame("frame2")

selenium还提供了一个切换到父frame的方法,比如我们切换到frame2之后,要想切换到frame1操作,则不需要先切回主界面再切换到frame,而是使用如下方法:

driver.switch_to.parent_frame()

需要注意的是,如果当前已经是主页面,则使用此方法无效

cookies操作

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time

chrome_options = Options()
chrome_options.page_load_strategy = 'eager'
service = Service('chromedriver.exe路径')

driver = webdriver.Chrome(service=service, options=chrome_options)
driver.get("https://www.baidu.com")
#print(driver.get_cookies())
#转换为字典格式
cookies = {}
for data in driver.get_cookies():
    cookies[data['name']] = data['value']
#字典推导式
cookies1= {data['name']: data['value']for data in driver.get_cookies()}
print(cookies)
print(cookies1)
driver.delete_cookie('CookieName') #删除一条cookie
driver.delete_all_cookies() #删除所有cookie

页面等待

强制等待

time.sleep()

缺点:不智能:设置的时间短,元素还没有加载出来;设置的时间长,则会浪费时间

隐式等待

隐式等待针对的是元素定位(设置一次,所有元素定位都会按照设定),隐式等待设置了一个时间,在一段时间内判断元素是否定位成功,如果完成了,就进行下一步;如果在设置的时间内没有定位成功,则会报超时加载

#隐式等待
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time

chrome_options = Options()
chrome_options.page_load_strategy = 'eager'
service = Service('chromedriver.exe路径')

driver = webdriver.Chrome(service=service, options=chrome_options)
driver.implicitly_wait(5) #设置隐式等待时间为5秒
driver.get("https://www.baidu.com")
driver.find_element(By.ID, 'kkww') #5秒钟内定位不到元素,报错

显式等待

明确等待某一个元素

每经过多少秒就查看一次等待条件是否达成,如果达成就停止等待,继续执行后续代码;如果没有达成就继续等待直到超过规定的时间后报超时异常

多用于软件测试,想要了解请自行查找

Chrome无界面模式

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time

chrome_options = Options()
chrome_options.page_load_strategy = 'eager'
service = Service('chromedriver.exe路径')
chrome_options.add_argument("--headless")    #添加开启无界面模式的命令
chrome_options.add_argument("--disable-gpu") #添加开启禁用gpu的命令

driver = webdriver.Chrome(service=service, options=chrome_options)
driver.get("https://www.baidu.com")
driver.save_screenshot('baidu.png')

配置代理:chrome_options.add_argument("--proxy-server=http://113.254.44.242:8382")

注意:更换ip代理必须重启浏览器

配饰UserAgent:``chrome_options.add_argument(“–user-agent=XXXX”)`

案例

【Python爬虫】案例_斗鱼

  • 31
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值