一、引言
Selenium环境的相关配置比较繁琐,此外,有的网站会对selenium和webdriver进行识别和反爬,因此在这里介绍一下它的替代产品Pyppeteer。
Pyppeteer 就是依赖于 Chromium 这个浏览器来运行的。如果第一次运行的时候,Chromium 浏览器没有安装,那么程序会帮我们自动安装和配置,就免去了繁琐的环境配置等工作。另外 Pyppeteer 是基于 Python 的新特性 async 实现的,所以它的一些执行也支持异步操作,效率相对于 Selenium也有所提高。
二、安装
pip3 install pyppeteer
三、快速入门
# coding:utf-8 import asyncio from pyppeteer import launch async def main(): # 创建浏览器对象 browser = await launch(headless=False,args=['--disable-infobars']) # 打开新的标签页 page = await browser.newPage() #设置视图大小 await page.setViewport({'width':1366,'height':768}) #设置UserAgent await page.setUserAgent('Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36') # 访问页面 response = await page.goto('https://www.baidu.com') #获取status、headers、url print(response.status) print(response.headers) print(response.url) #获取当前页标题 print(await page.title()) #获取当前页内容 print(await page.content()) #文本类型 # print(await response.text()) #cookie操作 print(await page.cookies()) #获取cookie,[{'name':xx,'value':xxx...},...] # page.deleteCookie() 删除cookie # page.setCookie() 设置cookie #定位元素 #1、只定位一个元素(css选择器) # element = await page.querySelector('#s-top-left > a') #2、css选择器 elements = await page.querySelectorAll('#s-top-left > a:nth-child(2n)') #3、xpath # elements = await page.xpath('//div[@id="s-top-left"]/a') for element in elements: print(await (await element.getProperty('textContent')).jsonValue()) #获取文本内容 print(await (await element.getProperty('href')).jsonValue())#获取href属性 #模拟输入和点击 await page.type('#kw','中国',{'delay':1000}) #模拟输入,输入时间:1000 ms await asyncio.sleep(2) await page.click('#su') #模拟点击,也可以先定位元素,然后await element.click() await asyncio.sleep(2) #执行js,滚动页面到底部 await page.evaluate('window.scrollTo(0,document.body.scrollHeight);') #截图 await page.screenshot({'path':'baidu.png'}) await asyncio.sleep(5) await browser.close() #关闭浏览器 asyncio.get_event_loop().run_until_complete(main())
四、主要操作
-
打开浏览器
-
调用 launch 方法即可,相关参数介绍:
- ignoreHTTPSErrors (bool): 是否要忽略 HTTPS 的错误,默认是 False。
- headless (bool): 是否启用无界面模式,默认为 True。如果 devtools 这个参数是 True 的话,那么该参数就会被设置为 False。
- executablePath (str): 可执行文件的路径,如果指定之后就不需要使用默认的 Chromium 了,可以指定为已有的 Chrome 或 Chromium。
- args (List[str]): 在执行过程中可以传入的额外参数。
- slowMo (int|float): 设置这个参数可以延迟pyppeteer的操作,单位是毫秒.
- userDataDir (str): 即用户数据文件夹,即可以保留一些个性化配置和操作记录。
- devtools (bool): 是否为每一个页面自动开启调试工具,默认是 False。如果为 True,那么headless参数会被强制设置为 False。
-
-
关闭提示条:”Chrome 正受到自动测试软件的控制”
browser = await launch(headless=False, args=['--disable-infobars'])
-
设置视图大小
width, height = 1366, 768 await page.setViewport({'width': width, 'height': height})
-
设置UserAgent
await page.setUserAgent('xxx')
-
执行JS脚本:调用page.evaluate()方法
await page.evaluate('window.scrollTo(0,document.body.scrollHeight);') #滚动页面到底部
-
规避webdriver检测
import asyncio from pyppeteer import launch async def main(): browser = await launch(headless=False, args=['--disable-infobars']) page = await browser.newPage() await page.goto('https://login.taobao.com/member/login.jhtml?redirectURL=https://www.taobao.com/') await page.evaluate( '''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => false } }) }''') await asyncio.sleep(100) asyncio.get_event_loop().run_until_complete(main())
-
模拟输入和点击
await page.type(selector, text, {"delay":100}) #模拟输入,输入每个字符的间隔时间100 ms await asyncio.sleep(2) await page.click(selector) #模拟点击 await asyncio.sleep(2)
-
鼠标操作
await page.hover(selector) #鼠标移动到某个元素上 await page.mouse.down() #按下鼠标 await page.mouse.move(2000, 0, {'delay': random.randint(1000, 2000)}) #移动鼠标 await page.mouse.up() #松开鼠标
-
定位元素、获取元素文本内容和属性值
- page.querySelector(selector)#只匹配第一个元素
element = await page.querySelector('#s-top-left > a') print(await (await element.getProperty('textContent')).jsonValue()) #获取文本内容 print(await (await element.getProperty('href')).jsonValue())#获取href属性
- page.querySelectorAll(selector)#css选择器
elements = await page.querySelectorAll('#s-top-left > a:nth-child(2n)') for element in elements: print(await (await element.getProperty('textContent')).jsonValue()) #获取文本内容 print(await (await element.getProperty('href')).jsonValue())#获取href属性
- page.xpath(expression)#xpath
elements = await page.xpath('//div[@id="s-top-left"]/a') for element in elements: print(await (await element.getProperty('textContent')).jsonValue()) #获取文本内容 print(await (await element.getProperty('href')).jsonValue())#获取href属性
- page.jeval(selector,pageFunction)#定位元素,并调用js函数去执行
print(await page.Jeval('#s-top-left > a:first-child','node => node.textContent') ) #获取文本内容 print(await page.Jeval('#s-top-left > a:first-child','node => node.href') ) #获取href属性
- page.querySelector(selector)#只匹配第一个元素
-
针对frame操作
- page.frames获取页面中的所有frames列表,对于每一个frame操作,和page操作一致
- page.mainFrame获取当前页面的主frame
frame_list = page.frames #获取所有frame #获取当前页面的标题,两者效果一样 print(await frame_list[0].title()) print(await page.mainFrame.title())