
谁说浏览器不能自动化大家好, 我是花姐。就在几天之前, 由于工作需要加班, 一直忙到了深夜时分, 整个人已经困得不成样子了, 但是在手头还剩下一个网页表单需要填写完毕之后才能够离开工作岗位去休息, 在这样的状况之下, 脑子里头突然就闪现出来一个比较奇特的想法。 不是万能的吗干嘛不用它自动填表于是, 我打开那个空白之处, 在里面摸索了一会儿, 过了五分钟的时间把代码给写好, 让表单一键填写完毕, 随即合上电脑的盖板, 顺手拎起包然后走人。这种种感觉让人非常开心, 简直到了极点, 让人觉得太爽了。因此今天就来聊聊一个自动化测试库, 它的速度比现有方案还要快, 能让你的浏览器变成听话的小猫咪它到底是什么东西? 它相比于别的东西, 优势究竟体现在什么地方?这个家伙是微软开源的一款用来做浏览器自动化测试的工具, 它支持各种各样的浏览器, 比如说Edge等等, 它还能够在那种不显示图形界面的无头模式下面去运行。之所以会出现这样的情况, 是因为它速度更快的主要原因在于:总而言之, 它完全能够用来实现自动化的网页内容爬取操作、自动化地填写各类表格、自动化地进行页面截图工作、以及自动化地采集所需数据, 并且还可以广泛适用于自动化测试等各种不同的场景需求。关于安装的这件事。操作起来特别的简单。基本上在三秒之内就可以搞定了。pip install playwrightplaywright install先执行第一个命令, 把它给装上, 然后执行第二个命令, 用来下载浏览器内核, 这是因为如果不下载浏览器内核的话, 它就无法成功地控制浏览器。在完成执行这一动作之后, 你所获得的那个东西, 现在已经是拥有这样一种让浏览器去乖乖听你的话的这般能力了的啦Hello 让浏览器跑起来来看一个简单的例子, 咱们先把百度给打开呢, 然后呢再来进行截图。from playwright.sync_api import sync_playwrightdef run():with sync_playwright() as p:browser p.chromium.launch()page browser.new_page()page.goto(https://www.baidu.com)page.screenshot(pathbaidu.png)browser.close()run()代码解析的说明如下: ()代表启动过程, 它会支持使用 with 语法这一种方式, 这样做是为了保证在程序结束之后的资源能够被正确释放掉。p..()同样是用于启动, 并且你也可以选择使用 p..()来进行操作。page.goto()这段代码的作用是进行百度网站的访问操作。page.(pathbaidu.png)则是负责截图功能。最后一步是使用.close()方法来完成整个浏览器的关闭任务。你执行完代码之后, 你的项目目录下面就会多出一个叫做的文件, 你打开这个文件看一下, 百度首页是不是安安稳稳地待在里面?这个功能是可以自动填写表格的,它的速度比你用手填写的速度要快一百倍之多。很多的网站里面的登录页、搜索框以及表单, 这些内容都能够利用相应的方法轻松完成处理, 举例来说的话, 就是在打开百度这个网站之后, 接着在其中输入想要搜索的那些相关内容:from playwright.sync_api import sync_playwrightimport timedef run():with sync_playwright() as p:browser p.chromium.launch(headlessFalse)page browser.new_page()page.goto(https://www.baidu.com)page.fill(.s_ipt, Python) # 输入Pythonpage.click(input[typesubmit]) # 点击登录按钮page.screenshot(pathbaidu_search.png)time.sleep(10) # 方便大家查看效果 这里等待10秒browser.close()run()代码解析在执行操作之后, 你就会发现, 浏览器自动打开了百度网页, 并且会输入关键词, 接着进行相应的搜索工作。整个流程进行得非常顺利, 一点也不拖泥带水, 那种感觉简直就和电影里面刻画的黑客场景是一模一样的对用户的操作进行模拟, 这些动作包括滑动、点击以及拖拽。让 模拟用户操作这件事, 可以说是非常简单, 比如说滚动页面、点击按钮以及拖拽元素这样的动作, 都算是例子。page.click(button.submit) # 点击按钮page.hover(#menu) # 鼠标悬停page.mouse.wheel(0, 500) # 模拟滚动鼠标向下滚 500 像素page.drag_and_drop(#source, #target) # 拖拽元素你可以根据实际情况去使用这个办法, 来完成那些需要自动化的事儿, 比如像去点击广告、去滚动那个页面、去拖拽移动文件, 再不就是去进行那个抢购秒杀商品的操作, 当然这里呢是带着一点开玩笑的意思去说的。网页上的元素该怎么进行定位呢? 这第一步需要把谷歌浏览器给打开。你需要把目标网站的网址填入那个地方, 之后再去按下设备上的F12功能键, 这样做能够把你电脑里自带的开发者工具给打开。请点击被标注为红框的那个位置里面的按钮。你可以把鼠标移到你想要查看的那个控件所在的具体位置, 这样的话就能够看到该控件所对应的id、class以及类型了。比如, 当你想要查看百度输入框这个控件中所包含的内容的时候, 按照上面的方法进行操作即可。我们能够清晰地辨别出, 在百度的输入框这里, 它所对应的标签类型是input, 它的id属性值是kw, 同时它的class属性值是s_ipt。2. 现在大家用代码来写规则, 然后通过这些代码就能管得住那些指出来的控件。至于怎么找到元素, 也就是定位元素这事儿, 它的核心想法是什么呢。这个定位器其实就是支撑它自动等待和重试能力的核心关键部分所在的地方, 因为它能够智能地去等待那些需要加载的元素到位, 并且配合着重试的机制, 从而避免因为网络延迟或者动态渲染这些原因导致的定位失败这一情况发生, 所以建议大家一定要优先去使用那些有语义化的定位器, 比方说角色或者是文本这种类型的方式, 而不是一味地再去用传统的那些css或者x xpath这些方式, 这样做主要是为了把代码的可读性以及它的稳定性给提高上去。2.1. CSS 选择器使用HTML标签或者是类名的形式, 亦或是采取标识符的方式, 用这些CSS语法规定的东西去找到对应的对象。# 定位 ID 为 username 的输入框page.locator(#username).fill(admin)# 定位类名为 submit-btn 的按钮page.locator(button.submit-btn).click()具体的使用范围是, 这些元素存在固定的标识符或者是类名称, 又或者是需要用到那种层级关系的嵌套方式来进行选择, 比方说通过大于号来连接外层标签和内层标签这样的操作形式。2.第二, 关于Xpath表达式这个问题。可以通过使用XML路径语言这种语法工具, 去对那些结构比较复杂的内容进行位置的查找和定位。# 定位 name 属性为 email 的输入框page.locator(//input[nameemail]).fill(testexample.com)# 定位包含特定文本的按钮page.locator(//button[contains(text(), 提交)]).click()该方法的适用范围是在元素的属性发生动态变化, 并且需要进行复杂的条件筛选的时候。2.3. 根据角色的定位来进行操作, 具体就是角色这个定位的部分。这主要是建立在关于ARIA角色的基础之上, 同时也结合了那些可访问性的属性, 从这样一个角度来看的话, 其结果就是最贴近于用户的实际感知情况了。# 定位名称为 登录 的按钮page.get_by_role(button, name登录).click()# 定位角色为输入框且名称为 用户名page.get_by_role(textbox, name用户名).fill(user123)支持的角色有: 、link、、等。2.这个4是根据那个文本的内容去给它做一个定位。# 精确匹配文本page.get_by_text(欢迎回来).click()# 正则表达式模糊匹配page.get_by_text(re.compile(r订单编号\d)).hover()当适用场景是元素本身不存在那些固定的属性, 但是里面的文本内容却是保持稳定的时候, 这种情况是可以被使用的。2.5, 它是按照标签来实现关联并且进行定位操作的。# 通过关联的 文本定位输入框page.get_by_label(密码).fill(secret)# 通过占位符定位page.get_by_placeholder(请输入手机号).type(13800138000)它的优势在于, 它跟表单控件天然就是绑定在一起的。这样的好处是, 能够避免层级依赖的问题。2.这个动作是要通过使用那个测试 ID, 从而把具体的目标给精准定位到的。这个属性是专门为了测试的目的而设置的, 需要在页面的时候去添加一个># 定位>page.get_by_test_id(submit-button).click()最好的做法就是让开发人员把唯一测试这个 ID 约定起来, 这样做的目的是为了提升定位的稳定性。在动态元素处理的技巧里面, 有一个点需要大家注意, 第一个点就是用显式等待的方法把元素加载出来。# 等待元素可见后再操作page.locator(.loading).wait_for(statevisible)# 等待元素消失page.wait_for_selector(.spinner, statehidden)2. 将处理嵌套这一操作, 拆解开, 来进行。# 定位到 iframe 内的元素iframe page.frame(namepayment-iframe)iframe.get_by_text(确认支付).click()3. DOM 穿透通过那个大大的、指向右边的 这个符号, 去穿透掉那个DOM的层级结构。page.locator(div#shadow-host input.custom-input).fill(data)在面对复杂场景进行定位的时候, 其策略之一是采用多重条件筛选。# 定位类名为 item 且包含文本 特价 的元素page.locator(.item, has_text特价).click()# 组合角色和文本过滤page.get_by_role(listitem).filter(has_text待付款).nth(0).click()2. 相对定位# 父子关系定位parent page.locator(div.parent)child parent.locator(span.child)# 兄弟元素定位second_item page.locator(ul li).nth(1)3. 动态列表处理# 遍历商品列表并点击第三个商品items page.locator(.product-list li)await items.nth(2).click()# 根据文本动态定位最新添加的条目new_item page.locator(tr:has-text(2024-03-18)).last关于这个对比, 你需要做出选择的是哪一方具体的功能是什么。速度更快较慢多浏览器支持内置是必须要进行驱动。无头模式默认支持需手动设置等待元素加载自动地执行等待的动作。需手动 sleepAPI 自动化支持不支持移动端模拟支持需插件如果你需要去做自动化测试, 或者要去写爬虫, 又或者是模拟在网页上进行填表操作的话, 那么它绝对是你的优先选择。但是的话, 如果你的项目已经基于某些特定的技术或平台了, 那也没有必要说急着去更换掉原来的东西。结尾部分要说的是, 用这个东西可以把双手给解放出来。在你学会了以后, 你会发觉你的整个眼里的世界都是完全不一样的。总而言之呢, 只要是那些需要你用手亲自去进行操作的网页上面所包含的任务内容, 这些任务在大部分的情形之下基本上都是能够经由自动化的方式来实现完成的。在接下来的这一期内容当中, 我们接着会为大家详细去介绍那个基于相关的这样一个实际的项目操作, 这个项目的具体任务就是去进行爬取来自那些提供免费素材的网站之上的某一个特定用户的图片, 并且把这些所获取到的图片全部保存到本地电脑上。