由于Selenium流行已久,现在稍微有点反爬的网站都会对selenium和webdriver进行识别,网站只需要在前端js添加一下判断脚本,很容易就可以判断出是真人访问还是webdriver。
虽然也可以通过中间代理的方式进行js注入屏蔽webdriver检测,但是webdriver对浏览器的模拟操作(输入、点击等等)都会留下webdriver的标记,
同样会被识别出来,要绕过这种检测,只有重新编译webdriver,麻烦自不必说,难度不是一般大。
由于Selenium具有这些严重的缺点。pyperteer成为了爬虫界的又一新星。
相比于selenium具有异步加载、速度快、具备有界面/无界面模式、伪装性更强不易被识别为机器人,同时可以伪装手机平板等终端;
虽然支持的浏览器比较单一,但在安装配置的便利性和运行效率方面都要远胜selenium。
优点
安装配置的便利性和运行效率方面都要远胜 selenium
支持 asyncio 异步协程,对于并发比较友好
缺点
编程语言只能用javascript
支持的浏览器比较单一,只能用chromium
是第三方的,好久没有更新了,bug 也不少,Pyppeteer 所依赖的 Puppeteer 的原生 JS 版本,本身就很不稳定
Pyppeteer 就是依赖于 Chromium 这个浏览器来运行的。
那么有了 Pyppeteer 之后,我们就可以免去那些繁琐的环境配置等问题。
如果第一次运行的时候,Chromium 浏览器没有安装,那么程序会帮我们自动安装和配置,就免去了繁琐的环境配置等工作。
另外 Pyppeteer 是基于 Python 的新特性 async 实现的,所以它的一些执行也支持异步操作,效率相对于 Selenium 来说也提高了。
运行程序会自动下载chromium
pyppeteer无疑为防爬墙撕开了一道大口子,针对selenium的淘宝、美团、文书网等网站,目前可通过该库使用selenium的思路继续突破,毫不费劲。
介绍Pyppeteer之前先说一下Puppeteer,Puppeteer是谷歌出品的一款基于Node.js开发的一款工具,主要是用来操纵Chrome浏览器的 API,通过Javascript代码来操纵Chrome浏览器,完成数据爬取、Web程序自动测试等任务。
pyppeteer是非官方 Python 版本的 Puppeteer 库,浏览器自动化库,由日本工程师开发。
Puppeteer是 Google 基于 Node.js 开发的工具,调用 Chrome 的 API,通过 JavaScript 代码来操纵 Chrome 完成一些操作,用于网络爬虫、Web 程序自动测试等。
pyppeteer 使用了 Python 异步协程库asyncio,可整合 Scrapy 进行分布式爬虫。
puppet 木偶,puppeteer 操纵木偶的人。
pip install pyppeteer
下面是pyppeteer的使用案例,可以模拟登录京东,详细代码粉丝可以找我要
滑动验证案例
验证码识别
pip install opencv-python
模拟京东登录
import random
from pyppeteer import launch
import asyncio
import cv2
from urllib import request
解释:launch 方法会新建一个 Browser 对象,然后赋值给 browser,然后调用 newPage 方法相当于浏览器中新建了一个选项卡,同时新建了一个 Page 对象。
然后 Page 对象调用了 goto 方法就相当于在浏览器中输入了这个 URL,浏览器跳转到了对应的页面进行加载,
加载完成之后再调用 content 方法,返回当前浏览器页面的源代码。
在这个过程中,我们没有配置 Chrome 浏览器,没有配置浏览器驱动,免去了一些繁琐的步骤,同样达到了 Selenium 的效果,还实现了异步抓取,爽歪歪!
开启浏览器
调用 launch() 方法即可,相关参数介绍:这些参数用字典包裹
关闭提示条:”Chrome 正受到自动测试软件的控制”,这个提示条有点烦,那咋关闭呢?这时候就需要用到 args 参数了,禁用操作如下:
browser = await launch(headless=False, args=[‘–disable-infobars’])
可以手动调用setViewport方法设置显示页面的长宽像素。设置如下:
import asyncio
from pyppeteer import launch
width, height = 1366, 768
async def main():
browser = await launch(headless=False)
page = await browser.newPage()
await page.setViewport({'width': width, 'height': height})
await page.goto('https://www.taobao.com')
await asyncio.sleep(3)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
执行js程序:拖动滚轮。调用evaluate方法。
#执行js代码
await page.evaluate(‘window.scrollTo(0,document.body.scrollHeight)’)
# 打印页面文本
page_text = await page.content()
模拟登录京东,并且可以实现滑块验证,需要的粉丝可以找我要代码
import random
from pyppeteer import launch
import asyncio
import cv2
from urllib import request
原因:
需要安装依赖库
yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 -y
pyppeteer需要在没有沙盒arg的情况下运行
#创建浏览器
browser = await launch({
#“headless”: False, # headless指定浏览器是否以无头模式运行,默认是True。
“args”: [‘–window-size=1366,768’,‘–disable-infobars’,‘–no-sandbox’],
})
谨记,一旦找不到元素,大概率是iframe问题
import random
import time
from pyppeteer import launch
import asyncio
from urllib import request
async def main():
#创建浏览器
browser = await launch({
“headless”: False, # headless指定浏览器是否以无头模式运行,默认是True。
“args”: [‘–window-size=1366,768’,‘–disable-infobars’,‘–no-sandbox’],
})
# 打开新的标签页
page = await browser.newPage()
# 设置页面大小一致
await page.setViewport({"width": 1366, "height": 768})
# 访问页面
await page.goto("https://qian.cainiao.com/login#/login?_k=jocblt")
await page.waitFor(3000)
#查看iframe
frame = page.frames
for i in frame:
print(i.name)
await page.waitFor(2000)
**#切换iframe**
**frame = frame[2]**
print(frame)
#pyppeteer通过xpath路径点击元素,先找到元素,得到的是个列表,然后根据元素点击
element =await frame.xpath(‘//*[@id=“login-tabs”]/div[2]’)
print(“取到的元素是”,element)
#根据元素点击
await element[0].click()
await frame.waitFor(1000)
#输入手机号
await frame.type("#fm-sms-login-id", '18xxx323428', {
"delay": random.randint(80, 120)
})
await frame.waitFor(1000)
#点击发送验证码
await frame.click(".send-btn-link")
await frame.waitFor(3000)
#再次切换iframe
frame = page.frames[3]
el = await frame.J("#nc_1_n1z")
# el = await frame.xpath('//*[@id="nc_1_n1z"]')
print("el为:",el)
# # 获取元素的边界框,包含x,y坐标
box = await el.boundingBox()
print("box为",box)
await frame.waitFor(1000)
await frame.hover("span.btn_slide")
await page.mouse.down()
# # steps 是指分成几步来完成,steps越大,滑动速度越慢
# #在自己的原有位置,平移多少距离
await page.mouse.move(box["x"] + 276, box["y"], {"steps": 180})
await frame.waitFor(1000)
await page.mouse.move(box["x"] + 276+34, box["y"], {"steps": 100})
await page.mouse.up()
#关闭浏览器也要await
await browser.close()
if name == ‘main’:
loop = asyncio.get_event_loop()
loop.run_until_complete(main())