php - 无头 Chromium 浏览器始终显示验证码
问题描述
我正在使用带有headless-chromium-php 的google chrome 无头浏览器
导航到某些网站,但它总是被验证码检测到
我尝试使用此插件随机更改用户代理
但没有任何改变
$UserAgent = \Campo\UserAgent::random([
'os_type' => 'Windows',
'device_type' => 'desktop'
]);
$browserFactory = new BrowserFactory('/opt/google/chrome/google-chrome');
$browser = $browserFactory->createBrowser([
'sendSyncDefaultTimeout' => 5000,
'userAgent' => $UserAgent
]);
$page = $browser->createPage();
$page->navigate($NextURL)->waitForNavigation();
为什么会这样?
解决方案
我强烈建议您阅读以下两篇文章并将所有这些技术应用到您的代码中,以使 Chrome Headless 检测变得更加困难
无头浏览器检测器通常使用一系列技术来识别您的浏览器是否被远程控制,例如,一些浏览器环境属性:
用户代理(旧)
它是常用来检测操作系统以及用户浏览器的属性。在具有 Chrome 版本 63 的 Linux 计算机上,它具有以下值:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/63.0.3071.115 Safari/537.36
因此,我们可以检查是否存在 Chrome Headless:
if (/HeadlessChrome/.test(window.navigator.userAgent)) {
console.log('Chrome headless detected!')
}
网络驱动程序(新)
为了自动化 Chrome 无头,一个新的属性 webdriver 被添加到 navigator 对象(参见 Chromium 代码)。因此,通过测试该属性是否存在,可以检测 Chrome 无头。
if (navigator.webdriver) {
console.log('Chrome headless detected!')
}
铬(新)
window.chrome
是一个似乎为 Chrome 扩展开发者提供功能的对象。虽然它在香草模式下可用,但在无头模式下不可用。
if (!window.chrome) {
console.log('Chrome headless detected')
}
权限(新)
目前无法在无头模式下处理权限。因此,它会导致 Notification.permission 和 navigator.permissions.query 报告矛盾值的不一致状态。
const permissionStatus = await navigator.permissions.query({ name: 'notifications' })
if (Notification.permission === 'denied' && permissionStatus.state === 'prompt') {
console.log('This is Chrome headless!')
} else {
console.log('This is not Chrome headless')
}
插件(旧)
navigator.plugins
返回浏览器中存在的插件数组。通常,在 Chrome 上,我们会找到默认插件,例如 Chrome PDF 查看器或 Google Native Client。相反,在无头模式下,返回的数组不包含插件。
if (navigator.plugins.length === 0) {
console.log('Chrome headless detected!')
}
语言(旧)
在 Chrome 中,有两个 Javascript 属性可以获取用户使用的语言:navigator.language 和 navigator.languages。第一个是浏览器 UI 的语言,而第二个是表示用户首选语言的字符串数组。但是,在无头模式下,navigator.languages 返回一个空字符串。
if (navigator.languages === '') {
console.log('Chrome headless detected')
}
WebGL
WebGL 是一种在 HTML 画布中执行 3D 渲染的 API。使用此 API,可以查询图形驱动程序的供应商以及图形驱动程序的渲染器。
使用普通的 Chrome 和 Linux,我获得了渲染器和供应商的以下值:“Google SwiftShader”和“Google Inc.”。在无头模式下,我获得了“Mesa OffScreen”,这是用于不使用任何类型的窗口系统进行渲染的技术和“Brian Paul”,这是启动开源 Mesa 图形库的程序。
const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl')
const debugInfo = gl.getExtension('WEBGL_debug_renderer_info')
const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL)
const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL)
if (vendor == 'Brian Paul' && renderer == 'Mesa OffScreen') {
console.log('Chrome headless detected')
}
缺少图片
最后,我们的最后一个发现(似乎也是最可靠的)来自 Chrome 在无法加载图像时使用的图像尺寸。
在 vanilla Chrome 的情况下,图像的宽度和高度取决于浏览器的缩放比例,但不为零。在无头 Chrome 中,图像的宽度和高度均为零。
const img = document.createElement('img')
img.src = "http://iloveponeydotcom32188.jg"
document.body.appendChild(img)
img.onerror = () => {
if (img.width == 0 && img.height == 0) {
console.log('Chrome headless detected')
}
}
推荐阅读
- php - 在 Wordpress 帖子中间添加自定义内容
- ios - 填充tableview Swift 4时,日期组件与预期不匹配
- xamarin.forms - Xamarin.Forms 中 MemoryStream 中的图像为空
- android - 如何设置相对布局的布局参数?
- azure-devops - 如何在不合并/樱桃采摘的情况下将变更集应用到另一个分支?
- joomla3.0 - 无用户名和密码注册还是不注册?
- python - 如何避免在 matplotlib 中调用 latex(输出到 pgf)
- docker - 通过 docker 网络连接到 web 服务
- python - django递归模板渲染期间的运行时错误
- php - 通过 REST API (php) 在 Jira 中的受让人