Scrapy第十五篇:后起之秀-Playwright

阳光穿透心脏的1/2处 2024-04-08 10:05 145阅读 0赞

Playwright 是微软在 2020 年初开源的新一代自动化测试工具,它的功能类似于 Selenium、Pyppeteer 等,它的功能非常强大,使用便捷简单,缺点是更新较快,市面上相关文档又少。官网:

目录

1.安装

2.初始化

3.基本使用

4.代码生成

5.选择器

6.事件监听

6.正则表达式很多时候,点击的url后面会附带参数,这个参数是变动的,这是后需要用正则去匹配最典型的情况是等待一个页面加载:page.wait_for_url(http://xxxxx?id=123456)从源码可以看出我们是可以传入正则表达式的:编辑

7.滑动翻页

8.并发

9.实例

10.使用模板

11.使用经验


1.安装

  1. pip install playwright -i https://pypi.tuna.tsinghua.edu.cn/simple

2.初始化

  1. playwright install

3.基本使用

Playwright 支持两种模式:同步、异步。

同步模式:

  1. import time
  2. from playwright.sync_api import sync_playwright
  3. if __name__ == '__main__':
  4. # 浏览器上下文管理器
  5. with sync_playwright() as p:
  6. # 启动谷歌浏览器(关闭无头模式)
  7. driver = p.chromium.launch(headless=False)
  8. # 新建页面
  9. page = driver.new_page()
  10. # 访问网址
  11. page.goto('https://www.baidu.com')
  12. print(page.title())
  13. page.fill('xpath=//input[@id="kw"]', '杜兰特')
  14. page.click('xpath=//input[@id="su"]')
  15. # 关闭驱动
  16. time.sleep(5)
  17. driver.close()

异步模式:

  1. import asyncio
  2. from playwright.async_api import async_playwright
  3. async def main():
  4. # 浏览器上下文管理器
  5. async with async_playwright() as p:
  6. # 启动谷歌浏览器(关闭无头模式)
  7. driver = await p.chromium.launch(headless=False)
  8. # 新建页面
  9. page = await driver.new_page()
  10. # 访问网址
  11. await page.goto('https://www.baidu.com')
  12. title = await page.title()
  13. print(title)
  14. # 关闭驱动
  15. await driver.close()
  16. asyncio.run(main())

注意:with 用于上下文对象的管理,它可以返回一个上下文管理器,也就对应一个 PlaywrightContextManager 对象,无论运行期间是否抛出异常,它能够帮助我们自动分配并且释放 Playwright 的资源。

4.代码生成

Terminal执行:

  1. playwright codegen -o script.py

操作浏览器后,右边会生产相应的代码预览

3f284fe8f04c448e9350f0f81d6008c4.png

关闭浏览器后,会在同级目录生成script.py代码 ,可以直接执行。

5.选择器

  1. import time
  2. from playwright.sync_api import sync_playwright
  3. if __name__ == '__main__':
  4. # 浏览器上下文管理器
  5. with sync_playwright() as p:
  6. # 启动谷歌浏览器(关闭无头模式)
  7. driver = p.chromium.launch(headless=False)
  8. # 新建页面
  9. page = driver.new_page()
  10. # 访问网址
  11. page.goto('https://www.baidu.com')
  12. print(page.title())
  13. # xpath选择器(推荐,不同的模拟器有不同的写法,但是xpath都是相通的,一招鲜吃遍天)
  14. page.fill('xpath=//input[@id="kw"]', '杜兰特')
  15. # ID选择器
  16. page.click('#su')
  17. time.sleep(2)
  18. # class选择器
  19. page.fill('.s_ipt', '欧文')
  20. # 文本选择器
  21. page.click('text=百度一下')
  22. # 关闭驱动
  23. time.sleep(2)
  24. driver.close()

6.事件监听

Page 对象提供了一个 on 方法,它可以用来监听页面中发生的各个事件,比如 close、console、load、request、response 等等。一个典型的用法就是用来监听页面的ajax请求响应:

  1. import time
  2. import cchardet
  3. from playwright.sync_api import sync_playwright, Response
  4. # 监听Response回调函数
  5. def handle_response(response: Response):
  6. detect = cchardet.detect(response.body())
  7. if detect['encoding']:
  8. print(response.body().decode(detect['encoding']))
  9. if __name__ == '__main__':
  10. # 浏览器上下文管理器
  11. with sync_playwright() as p:
  12. # 启动谷歌浏览器(关闭无头模式)
  13. driver = p.chromium.launch(headless=False)
  14. # 新建页面
  15. page = driver.new_page()
  16. # 访问网址
  17. page.goto('https://spa6.scrape.center/')
  18. print(page.title())
  19. # 监听网络请求的Response
  20. page.on('response', handle_response)
  21. # 等待网络请求加载完毕
  22. page.wait_for_load_state('networkidle')
  23. time.sleep(2)
  24. driver.close()

" class="reference-link">6.正则表达式 很多时候,点击的url后面会附带参数,这个参数是变动的,这是后需要用正则去匹配 最典型的情况是等待一个页面加载:page.wait_for_url(http://xxxxx?id=123456) 从源码可以看出我们是可以传入正则表达式的:89b3463f9e3945568d005ad6c61bf83f.png

使用示例:

  1. page.wait_for_url(re.compile("https://www.abcd.xyz/web/index[\s\S]*"))

7.滑动翻页

  1. page.locator("body").press("PageDown")

8.并发

  1. import asyncio
  2. import time
  3. from playwright.async_api import async_playwright
  4. async def run(url):
  5. async with async_playwright() as playwright:
  6. # create a chromium browser instance
  7. chromium = playwright.chromium
  8. # browser = await chromium.launch()
  9. # create a bowser instance which headless is true
  10. browser = await chromium.launch(headless=False)
  11. # create two isolated browser contexts
  12. user_context = await browser.new_context()
  13. page = await user_context.new_page()
  14. await page.goto(url)
  15. await page.fill('xpath=//input[@id="kw"]', '杜兰特')
  16. await page.click('xpath=//input[@id="su"]')
  17. time.sleep(10)
  18. # await page2.goto('https://www.baidu.com')
  19. async def main():
  20. tasks = []
  21. urls = ['https://www.baidu.com', 'https://www.baidu.com', 'https://www.baidu.com']
  22. for url in urls:
  23. task = asyncio.ensure_future(run(url))
  24. tasks.append(task)
  25. await asyncio.gather(*tasks)
  26. if __name__ == '__main__':
  27. asyncio.run(main())

9.实例

  1. """
  2. 同步模式
  3. """
  4. import time
  5. from playwright.sync_api import sync_playwright, Page, Locator
  6. def handle_business(page: Page, url):
  7. """
  8. 逻辑处理
  9. :param page: 页面实例
  10. :param url: 访问地址
  11. :return:
  12. """
  13. page.goto(url)
  14. # 定位输入框
  15. """
  16. 定位!
  17. 1.xpath定位:【搜索框】locator_input = page.locator('xpath=//input[@id="kw"]')
  18. 2.元素属性定位:【搜索框】locator_input = page.locator('[name="wd"]')后者locator_input = page.locator('[class="s_ipt"]')
  19. 3.本文定位:【搜索按钮】locator_submit_button = page.locator('text="百度一下"')
  20. 4.id定位:【搜索按钮】locator_submit_button = page.locator('#su')
  21. 5.CSS定位:略
  22. 6.伪类①:is【如果定位不到text="百度一下",则定位#su】locator_submit_button = page.locator(':is([text="百度一下"]),#su')
  23. 7.伪类②:has
  24. 8.伪类③:hans-text
  25. """
  26. locator_input = page.locator('[class="s_ipt"]', ).filter()
  27. """
  28. 页面操作!
  29. 1.page.goto("https://example.com") # 前往页面
  30. 2.page.go_back(**kwargs) #前进
  31. 3.page.go_forward(**kwargs) # 后退
  32. 4.page.screenshot(path="screenshot.png") 截图
  33. 5.print(page.title()) # 打印当前页标题
  34. 6.print(page.url()) # 打印当前页URL
  35. 7.page.reload(**kwargs) # 重新加载当前页面
  36. """
  37. # 填写
  38. locator_input.fill('SpringBoot')
  39. # 定位提交按钮
  40. locator_submit_button: Locator = page.locator(':is([text="百度一下"]),#su')
  41. # 鼠标单击
  42. locator_submit_button.click()
  43. """
  44. 等待元素!
  45. 1.等待元素:page.wait_for_selector(selector="[class='page-item_M4MDr pc']", strict=False, state="visible", timeout=5000)
  46. state:
  47. - `attached` - 等待元素出现在DOM
  48. - `detached` - 等待元素消失在DOM
  49. - `visible` - 等待元素可访问
  50. - `hidden` - 等待元素隐藏
  51. strict:断言选择器元素唯一。
  52. 2.等待固定时间:page.wait_for_timeout(1000)
  53. 3.等待状态:page.wait_for_load_state(state="networkidle")
  54. state:
  55. - `domcontentloaded` - 等待DOM加载完毕
  56. - `load` - 等待加载事件完毕
  57. - `networkidle` - 等待网络闲置至少500ms(即网络加载完毕)
  58. """
  59. page.wait_for_load_state(state="networkidle")
  60. """
  61. 元素操作!
  62. 1.文本输入:locator_input.fill('SpringBoot')
  63. 2.获取节点属性:attribute = page.get_attribute("#su", "type")
  64. 3.点击:locator_submit_button.click()或者page.click("#su")
  65. """
  66. time.sleep(50)
  67. if __name__ == '__main__':
  68. # 浏览器上下文管理器
  69. with sync_playwright() as p:
  70. # 创建浏览器驱动
  71. browser = p.chromium.launch(headless=False)
  72. # 创建浏览器实例
  73. context = browser.new_context()
  74. # 创建页面实例
  75. page = context.new_page()
  76. handle_business(page, 'https://www.baidu.com/')

10.使用模板

  1. import time
  2. from playwright.sync_api import sync_playwright
  3. if __name__ == '__main__':
  4. # 浏览器上下文管理器
  5. with sync_playwright() as p:
  6. # 启动谷歌浏览器(关闭无头模式)
  7. driver = p.chromium.launch(headless=False, args=["--start-maximized"])
  8. # 全屏
  9. context = driver.new_context(no_viewport=True)
  10. # 新建页面
  11. page = context.new_page()
  12. # 这里使用生成器生成!!!!TODO
  13. # 关闭驱动
  14. time.sleep(10)
  15. context.close()
  16. driver.close()

11.使用经验

①最好不要去手写,太影响效率,最好是使用生成器,然后复制进模板进行修改。

②生成器生成的代码,往往无法直接使用,因为很多定位器是动态的,无法使用,我们需要把动态的定位器换成固定的定位器。

③有些元素只有悬停才会出现,我们可以使用hover()

  1. page1.get_by_role("link", name="系统维护").hover()

④有些元素找不到、定位不到,可能是加载太慢了,我们可以先用xpath定位,等待元素出现

  1. # 先等待元素
  2. page1.wait_for_selector(
  3. selector='//div[@class="am-modal-dialog" and @style="width: 540px; height: 150px;"]//span[@class="am-modal-btn"]')
  4. # 再获取元素
  5. selector = page1.query_selector(
  6. selector='//div[@class="am-modal-dialog" and @style="width: 540px; height: 150px;"]//span[@class="am-modal-btn"]')
  7. # 最后操作元素
  8. selector.click()

⑤在循环里面做好异常捕获,并在捕获中将界面打回新一轮的起点。

⑥有时候跑得太快,下拉框没有选择进去,可以多执行几次。

  1. page1.frame_locator("iframe[style=\"min-height:322px\"]").locator(
  2. "select[name=\"orgCategory\"]").select_option(
  3. f"{number}")
  4. page1.frame_locator("iframe[style=\"min-height:322px\"]").locator(
  5. "select[name=\"orgCategory\"]").select_option(
  6. f"{number}")
  7. page1.frame_locator("iframe[style=\"min-height:322px\"]").locator(
  8. "select[name=\"orgCategory\"]").select_option(
  9. f"{number}")
  10. page1.get_by_text("确定").click()

发表评论

表情:
评论列表 (有 0 条评论,145人围观)

还没有评论,来说两句吧...

相关阅读