现阶段,selenium的反爬策略已经非常成熟了。
selenium最简单的伪装是变为开发者模式。这种模式下,window.navigator.webdriver变量会变成false。可以一定程度上避免被识别。方式如下:
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
driver = webdriver.Chrome(options=options)
但这种方式现阶段已经很无力了,原因是一旦使用selenium操作dom元素(包括ActionChains,execute_script等方法),chromedriver就会留下指纹特征,使用js轻易的就能识别出来你是在使用selenium。
而现在的js都是经过混淆加密,要找到这些指纹并且破解可真是一件蛋疼的事。
即便使用 mitmproxy 来过滤js,也难以解决这个问题。比较你需要先知道指纹所在的js,以及所有特征字符串。
这时候,就轮到 pyppeteer 登场了。
pyppeteer本是一个前端神器,是一个Nodejs
的库,支持调用Chrome的API来操纵Web
,相比较Selenium
或是PhantomJs
,它最大的特点就是它的操作Dom
可以完全在内存中进行模拟既在V8
引擎中处理而不打开浏览器。
当然python也有对它的支持。下面介绍一下如何在python中使用。
1. 安装pyppeteer
pip3 install pyppeteer
2. 下载安装并初始化chrome.exe
在安装完pyppeteer后,一次运行时会自动下载并初始化chrome.exe环境。当然,也可以手动。
运行以下代码
from pyppeteer import chromium_downloader
print(chromium_downloader.get_url())
print(chromium_downloader.chromiumExecutable.get('win64'))
print(chromium_downloader.check_chromium())
输出:
https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/575458/chrome-win32.zip
C:\Users\yq\AppData\Local\pyppeteer\pyppeteer\local-chromium\575458\chrome-win32\chrome.exe
True
第一个是下载地址,第二个是你本地的默认安装路径,第三个是校验是否已经成功安装了chromium环境。
3. 简单示例
安装完成后,可以简单跑一下看是否可以运行。
import asyncio
from pyppeteer import launch
async def main():
browser = await launch(headless=False, args=['--disable-infobars', '--no-sandbox'])
page = await browser.newPage()
await page.goto('http://www.baidu.com')
await asyncio.sleep(100)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
当然,第一步也可以直接到第三步,直接运行会自动安装环境,但是速度可能比较慢一些。
使用pyppeteer完成滑动验证
import asyncio
from pyppeteer import launch
def screen_size():
"""使用tkinter获取屏幕大小"""
import tkinter
tk = tkinter.Tk()
width = tk.winfo_screenwidth()
height = tk.winfo_screenheight()
tk.quit()
return width, height
async def main():
# headless 展示出页面
# 取消自动软件控制的展示
# userDataDir='./userdata' 保存本地的 Cache、Cookies 等 以便下次使用
# devtools=True 打开F12
browser = await launch(headless=False, args=['--disable-infobars'])
page = await browser.newPage()
await page.goto('https://www.qichacha.com/user_login?back=%2F')
width, height = screen_size()
# 最大化窗口
await page.setViewport({
"width": width,
"height": height
})
# 设置浏览器
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)'
' Chrome/74.0.3729.169 Safari/537.36')
# 防止被识别,将webdriver设置为false
await page.evaluate(
'''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => false } }) }''')
# 登录时的验证
normal_login = await page.xpath('//*[@id="normalLogin"]')
await normal_login[0].click()
# 滑动验证
await page.waitFor(1000)
await try_validation(page)
await page.waitFor(1000)
await page.close()
async def try_validation(page, distance=308):
# 将距离拆分成两段,模拟正常人的行为
distance1 = distance - 10
distance2 = 10
btn_position = await page.evaluate('''
() =>{
return {
x: document.querySelector('#nc_1_n1z').getBoundingClientRect().x,
y: document.querySelector('#nc_1_n1z').getBoundingClientRect().y,
width: document.querySelector('#nc_1_n1z').getBoundingClientRect().width,
height: document.querySelector('#nc_1_n1z').getBoundingClientRect().height
}}
''')
x = btn_position['x'] + btn_position['width'] / 2
y = btn_position['y'] + btn_position['height'] / 2
# print(btn_position)
await page.mouse.move(x, y)
await page.mouse.down()
await page.mouse.move(x + distance1, y, {'steps': 30})
await page.waitFor(800)
await page.mouse.move(x + distance1 + distance2, y, {'steps': 20})
await page.waitFor(800)
await page.mouse.up()
asyncio.get_event_loop().run_until_complete(main())
上面的代码在截止到2019年6月14日12时前,是可以成功破解企某查的滑动验证的。
最后声明下,本文为技术性分享,如有侵权请联系作者。
如果转载或引用,请注明本文地址。
https://blog.csdn.net/qq393912540/article/details/91956136