草庐IT

python爬虫(七)--------selenium自动化

零度℃192 2024-02-11 原文

一,基本使用

# pip install selenium -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
from selenium import webdriver  # # 驱动浏览器
from selenium.webdriver.common.by import By  #选择器
from selenium.webdriver.common.keys import Keys   #按键
from selenium.webdriver.support.wait import WebDriverWait  #等待页面加载完毕,寻找某些元素
from selenium.webdriver.support import expected_conditions as EC  ##等待指定标签加载完毕

# 1,驱动浏览器
browser = webdriver.Chrome()  

# 2,请求页面   --返回的数据封装在了browser对象里,不需要额外的变量接收
browser.get('https://www.baidu.com')  #调用浏览器驱动访问站点

# 3,拿到输入框
text_input = browser.find_element(By.ID,'kw') 

# 4,向输入框中写入内容
text_input.send_keys('爬虫')  

# 5,按下回车按钮 
text_input.send_keys(Keys.ENTER)

# 等待事件 -- 怕网速慢
wait = WebDriverWait(browser,100)  # 参数1:浏览器对象 参数2:时间(秒)

# 等待某元素出现 presence_of_element_located()传入的参数格式是一个元组
wait.until(EC.presence_of_element_located((By.ID,'result_tts_player')))

print(browser.current_url)  #查看url
print(browser.get_cookies())  #查看cookie
print(browser.page_source)  #查看源代码

# browser.close()  # 关闭浏览器

二,声明不同浏览器对象

from selenium import webdriver
browser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.PhantomJS()
browser = webdriver.Safari()

三,访问页面

from selenium import webdriver

# 声明Chrome浏览器对象
browser = webdriver.Chrome()

# 请求页面 
browser.get('https://www.taobao.com')

print(browser.page_source)  # 获取网页源代码

# browser.close()  # 关闭当前页面

四,查找元素

查找方法(python3.7之前版本)

  • find_element_by_id 根据id属性来定位
  • find_element_by_name 根据name元素来定位
  • find_element_by_xpath 根据xpath语法来定位
  • find_element_by_tag_name 根据标签名来定位
  • find_element_by_class_name 根据class的名字来定位
  • find_element_by_css_selector 根据css选择器来定位
  • 以下两种方法都是用来的定位超链接的,也就是对应html页面中的a标签,括号里传入的值就是a标签中的超链接文字
  • 两者的区别在于一个是完整的超链接文字,一个是可以只写部分超链接文字
  • find_element_by_link_text 需要完整的超链接文字
  • find_element_by_partial_link_text 可以只写部分超链接文字

源码经过修改之后的写法(python3.8版本)

  • find_element(By.ID,"id") 根据id属性来定位
  • find_element(By.NAME,"name") 根据name元素来定位
  • find_element(By.XPATH,"xpath语法") 根据xpath语法来定位
  • find_elemnt(By.TAG_NAME,"input") 根据标签名来定位
  • find_element(By.CLASS_NAME,"classname") 根据class的名字来定位
  • find_element(By.CSS_SELECTOR,"#id") 根据css选择器来定位
  • find_element(By.LINK_TEXT,"text") 根据文本属性

1,单个元素

from selenium import webdriver 
browser = webdriver.Chrome()
browser.get("http://www.baidu.com")

browser.find_element(By.LINK_TEXT,"新闻").click() # 通过.click()点击目标链接
from selenium import webdriver 
from selenium.webdriver.common.by import By  #选择器

browser = webdriver.Chrome()
browser.get('https://taobao.com')

# 通过元素ID查找 
by_id = browser.find_element(By.ID,'q')
by_id.send_keys('美食')
print(by_id)

# 通过css选择器查找
css_select = browser.find_element(By.CSS_SELECTOR,'#q')
css_select.send_keys('美食')

# 通过xpath查找  
xpath = browser.find_element(By.XPATH,'//*[@id="q"]')
xpath.send_keys('美食')

# browser.close()

2,多个元素

查找方法:

  • find_elements(By.ID,"id") 根据id属性来定位
  • find_elements(By.NAME,"name") 根据name元素来定位
  • find_elements(By.XPATH,"xpath语法") 根据xpath语法来定位
  • find_elemnts(By.TAG_NAME,"input") 根据标签名来定位
  • find_elements(By.CLASS_NAME,"classname") 根据class的名字来定位
  • find_elements(By.CSS_SELECTOR,"#id") 根据css选择器来定位
  • find_elements(By.LINK_TEXT,"text") 根据文本属性
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')

elements = browser.find_elements(By.CSS_SELECTOR,'.service-bd li')   
print(elements)  # 以列表形式返回
for i in elements:
    print(i)

五,元素的交互操作

对获取的元素调用交互方法
from selenium import webdriver
import time
from selenium.webdriver.common.by import By  #选择器
from selenium.webdriver.common.keys import Keys   #按键

browser = webdriver.Chrome()
browser.get('https://www.jd.com')
# 找到首页的输入框
text_input = browser.find_element(By.ID,'key')
#输入内容 
text_input.send_keys('iphone')
# 找到首页的搜索按钮
browser.find_element(By.CLASS_NAME,'button').click()

time.sleep(2)

# 找到详情页的输入框
text_input = browser.find_element(By.ID,'key')
# 清空原来输入的文本内容 
text_input.clear()
text_input.send_keys('ipad')  

# 找到详情页的搜索按钮
# browser.find_element(By.CSS_SELECTOR,'button.button.cw-icon').click()  # 单击

六、交互动作 ActionChains

将动作附加到动作链中串行执行
from selenium import webdriver
from selenium.webdriver import ActionChains

browser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)

'''
webDriver只能在一个页面上对元素识别和定位,
对于frame/iframe表单内嵌页面上的元素无法直接定位,
此时就需要通过switch_to.frame()方法将当前定位的主题切换为iframe表单的内嵌页面中
switch_to.frame()默认可以直接提取表单的id和name属性
'''
# 3.7   .switch.to.frame------python3.7版本
browser.switch_to.frame('iframeResult')  #将当前定位的主题切换为iframe表单的内嵌页面中

A = browser.find_element(By.CSS_SELECTOR,'#draggable')
B = browser.find_element(By.CSS_SELECTOR,'#droppable')

# 产生一个动作执行器
actions = ActionChains(browser)  
actions.drag_and_drop(A,B) # A移动到B
actions.perform()  # 执行动作链

 更多操作: 7. WebDriver API — Selenium Python Bindings 2 documentation

七、执行JavaScript 

selenium并不是万能的,有时候页面上操作无法实现的,这时候就需要借助JS来完成了

滚动页面方法execute_script()  该方法可调用原生JavaScript的api
滚动到底部:window.scrollTo(0,document.body.scrollHeight)
滚动到顶部:window.scrollTo(0,0)

说明:
window:js的window对象
scrollTo:window的方法,可以滚到页面的任何位置
scrollHeight:是dom元素的通用属性,document.body.scrollHeight会返回body元素的高度,基本上就是页面的高度
scrollLeft:获取位于对象左边界和窗口目前可见内容的最左端之间的距离
scrollTop:获取位于对象最顶端和窗口中可见内容的最顶端之间的距离
scrollWidth:获取对象滚动的宽度
from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.get('http://news.baidu.com/')
time.sleep(2)

#滚动到浏览器底部
js = 'window.scrollTo(0,document.body.scrollHeight)'
driver.execute_script(js)  # 执行js代码
time.sleep(3)

# # #滚动到顶部
js = 'window.scrollTo(0,document.body.scrollTop=0)'
driver.execute_script(js)

 八、获取元素信息

1,获取文本及属性值

.text 获取文本值

get_attribute() 根据属性获取属性值

from selenium import webdriver
from selenium.webdriver import ActionChains

browser = webdriver.Chrome()

url = 'https://www.zhihu.com/explore'
browser.get(url)

# 知乎 圆桌讨论
l = browser.find_elements(By.CSS_SELECTOR,'.ExploreRoundtableCard.ExploreHomePage-roundtableCard .ExploreRoundtableCard-header .ExploreRoundtableCard-title')
# print(l)
for i in l:
    print(i)
    print(i.text)
    print(i.get_attribute('href'))
    

# 找单个元素
logo = browser.find_element(By.XPATH,'//*[@id="special"]/div[2]/div/div[3]/div[1]/div[1]/a')
print(logo)
print(logo.text)
print(logo.get_attribute('href'))

九、等待

等待特定元素出现后做某事

通常用于等待某个网页元素加载完毕后进行后续操作,避免出现异常

显示等待

# 显示等待 明确要等到某个元素出现 等不到就一直等 除非在规定时间内都没找到 那么报出异常Exception
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait 
from selenium.webdriver.common.by import By  #选择器
from selenium.webdriver.support import expected_conditions as EC

browser = webdriver.Chrome()
browser.get('https://www.taobao.com/')

wait = WebDriverWait(browser, 280)  # 秒
#     等待特定元素是否存在于页面
input = wait.until(EC.presence_of_element_located((By.ID, 'J_Toolkit')))
print(input)

EC

EC模块的方法

导包:from selenium.webdriver.support import expected_conditions as EC

  • title_is 标题是某内容
  • title_contains 标题包含某内容
  • presence_of_element_located 元素加载出,传入定位元组,如(By.ID, 'p')
  • visibility_of_element_located 元素可见,传入定位元组
  • visibility_of 可见,传入元素对象
  • presence_of_all_elements_located 所有元素加载出
  • text_to_be_present_in_element 某个元素文本包含某文字
  • text_to_be_present_in_element_value 某个元素值包含某文字
  • frame_to_be_available_and_switch_to_it frame加载并切换
  • invisibility_of_element_located 元素不可见
  • element_to_be_clickable 元素可点击
  • staleness_of 判断一个元素是否仍在DOM,可判断页面是否已经刷新
  • element_to_be_selected 元素可选择,传元素对象
  • element_located_to_be_selected 元素可选择,传入定位元组
  • element_selection_state_to_be 传入元素对象以及状态,相等返回True,否则返回False
  • element_located_selection_state_to_be 传入定位元组以及状态,相等返回True,否则返回False
  • alert_is_present 是否出现Alert

详情链接:7. WebDriver API — Selenium Python Bindings 2 documentation

十、前进后退 

浏览器控制页面

import time
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.get('https://www.jd.com/')

browser.back()   # 后退  淘宝
time.sleep(2)

browser.forward()  # 前进  京东
time.sleep(2)

十一、选项卡管理

窗口切换 switch_to_window(窗口ID) switch_to.window(窗口ID) (python3.8以上版本都支持,python3.7只支持后者写法)

查看所有窗口ID window_handles

FAQ:只有切换到当前窗口时,才能操作当前窗口(比如翻页、获取源代码等等)

# 选项卡管理
# switch_to_window  窗口切换 
# window_handles 查看所有窗口
import time
from selenium import webdriver

browser = webdriver.Chrome()

browser.get('https://www.baidu.com'
           )  # 选项卡0  窗口0
# 调用原生JavaScript的api接口
browser.execute_script('window.open()')   # 选项卡1 窗口1
time.sleep(2)
browser.execute_script('window.open()')   # 选项卡2 窗口2
print(browser.window_handles)  # 查看当前浏览器所有窗口ID

# # 给新选项卡窗口访问目标站点  3.7 .switch.to.window
browser.switch_to.window(browser.window_handles[0])
browser.get('https://www.mi.com/')

browser.switch_to.window(browser.window_handles[1]) #加载窗口2 切换到窗口2
browser.get('https://www.taobao.com') # 窗口2  打开淘宝

browser.switch_to.window(browser.window_handles[2])
browser.get('https://jd.com')

browser.switch_to.window(browser.window_handles[1])
browser.page_source

十二、异常处理

知识点:异常处理模块所在位置

from selenium.common.exceptions import TimeoutException, NoSuchElementException

from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.find_element(By.ID,'kq')
# 异常处理
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException

browser = webdriver.Chrome()
try:
    browser.get('https://www.baidu.com')
except TimeoutException:
    print('Time out')
try:
    browser.find_element(By.ID,'hello')
except NoSuchElementException:
    print('No Element')
finally:   #无论try语句中是否抛出异常,finally中的语句一定会被执行
    browser.close()

详细文档:7. WebDriver API — Selenium Python Bindings 2 documentation

十三、反爬手段

# 设为开发者模式(无头模式) 避免被监测  配置文件对象
opt = webdriver.ChromeOptions()  # 配置文件对象
opt.add_experimental_option('excludeSwitches', ['enable-automation'])  # 写入参数
browser = webdriver.Chrome(options=opt)
browser.get('https://www.baidu.com')

有关python爬虫(七)--------selenium自动化的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  4. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  5. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  6. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  7. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  8. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  9. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  10. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

随机推荐