2017年网页抓取:先进的Headless Chrome技巧

2023-10-13 04:40

本文主要是介绍2017年网页抓取:先进的Headless Chrome技巧,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文:Web Scraping in 2017: Advanced Headless Chrome Tips & Tricks
作者: Martin Tapia
翻译:不二

Headless Chrome是Chrome 浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有 Chrome 支持的特性运行程序。相比于现代浏览器,Headless Chrome 更加方便测试web应用,获得网站的截图,做爬虫抓取信息等,也更加贴近浏览器环境。下面看看作者分享的使用Headless Chrome进行网页抓取的经验。

PhantomJS的研发已经停止,而Headless Chrome成了热门关注的焦点,大家都很喜欢它,包括我们。在Phantombuster公司,网页抓取是我们工作的很大一部分,现在我们广泛使用Headless Chrome。

这篇文章,将告诉你如何快速入门Headless Chrome生态系统,并展示从已经抓取数百万网页中学到的经验。

文章摘要:
1. 有很多库可以控制Chrome,可以根据自己的喜欢选择。
2. 使用Headless Chrome进行网页抓取非常简单,掌握下面的技巧之后更是如此。
3. Headless浏览器访客可以被检测到,但没人这么做。

Headless Chrome简述

Headless Chrome基于PhantomJS(QtWebKit内核)由谷歌Chrome团队开发。团队表示将专注研发这个项目,未来也会不断维护它。

这意味着对于网页抓取和自动化的需求,现在可以体会Chrome的速度和功能,因为它具备世界上使用最多的浏览器的特性:支持所有网站,支持JS引擎,还有伟大的开发者工具API。太可怕啦!

选用哪个工具控制Headless Chrome?


image

市面上确实有很多NodeJS库来支持Chrome新版headless模式,每一个都各有特色,我们自己的一款是NickJS。倘若没有自己的抓取库,怎么敢轻易的说自己是网页抓取专家。

还有一套C++ API和社区用其他语言发布的库,比如说基于GO语言。我们推荐使用NodeJS工具,因为它和网页解析语言一样(下面你会看到它有多便利)。

网页抓取?它不是非法的吗?

我们无意挑起无休止的争论,但不到两周前,美国一名地方法官下令允许第三方抓取领英(LinkedIn)公众档案。目前为止这只是初步的法令,诉讼仍会继续进行,领英肯定会反对,但尽管放心,我们会密切关注情况,因为这篇文章里谈论了很多关于领英的内容。

无论如何作为一篇技术性的文章,我们不会深入探究特定的抓取操作的合法性问题,我们应该始终努力去尊重目标网站的ToS。而对你在这篇文章中所学到的造成任何损害概不负责。

目前为止学到的很酷的东西

下面列出的一些技巧,我们每天几乎都在使用。代码示例采用NickJS抓取库,但它们很容易被其他Headless Chrome工具改写,重要的是分享概念。

把cookies放回cookie jar

使用功能齐全的浏览器抓取会让人安心,无需担心CORS、会话、cookie、CSRF和其他web问题。

但有时登录表单变得非常强硬,唯一的解决方案是恢复以前保存的会话cookie。当察觉故障时,有些网站会发送电子邮件或短信。我们就没有时间这么做,只是使用已设置好的会话cookie打开页面。

领英有一个很好的例子,设置li_atcookie能保证抓取机器访问他们的社交网络(请记住:注意尊重目标网站Tos)。

await nick.setCookie({name: "li_at",value: "a session cookie value copied from your DevTools",domain: "www.linkedin.com"
})

相信像领英这样的网站不会用一个有效的会话cookie来阻止一个真实的浏览器访问。这么做相当有风险,因为错误的信息会引发愤怒用户的大量支持请求。

jQuery不会让你失望

我们学到了一件重要的事,那就是通过jQuery从网页提取数据真是太容易了。现在回想起来,这是显而易见的。网站提供了一个高度结构化的、可查询的、包含数据元素的树(它被称为DOM),而jQuery是非常高效的DOM查询库。所以为什么不用它来抓取呢?这个技巧会屡试不爽。

很多网站都已经使用了jQuery,所以只需在页面中添加几行就可以得到数据。

await tab.open("news.ycombinator.com")
await tab.untilVisible("#hnmain") // Make sure we have loaded the page
await tab.inject("https://code.jquery.com/jquery-3.2.1.min.js") // We're going to use jQuery to scrape
const hackerNewsLinks = await tab.evaluate((arg, callback) => {// Here we're in the page context. It's like being in your browser's inspector toolconst data = []$(".athing").each((index, element) => {data.push({title: $(element).find(".storylink").text(),url: $(element).find(".storylink").attr("href")})})callback(null, data)
})
印度、俄罗斯和巴基斯坦屏蔽机器人的做法有什么共同之处?


image

答案就是利用验证码解决服务器验证。你可以几美元买到上千个验证码,通常产生验证码不到30秒。但晚上的时候,因为没有人,所以一般比较贵。

一个简单的谷歌搜索将提供多个api来解决任何类型的验证码问题,包括获取谷歌最新的recaptcha验证码(2美元1000个)。

将抓取机器连接到这些服务就如发出HTTP请求一样简单,现在机器人是人类了。

在我们的平台上,用户很容易解决他们需要的验证码问题。我们的巴斯特图书馆可以调用多个解决服务器验证:

if (await tab.isVisible(".captchaImage")) {// Get the URL of the generated CAPTCHA image// Note that we could also get its base64-encoded value and solve it tooconst captchaImageLink = await tab.evaluate((arg, callback) => {callback(null, $(".captchaImage").attr("src"))})// Make a call to a CAPTCHA solving serviceconst captchaAnswer = await buster.solveCaptchaImage(captchaImageLink)// Fill the form with our solutionawait tab.fill(".captchaForm", { "captcha-answer": captchaAnswer }, { submit: true })
}
等待的是DOM元素,而不是固定的时间

经常看到抓取初学者让他们的机器人在打开一个页面或点击一个按钮后等待5到10秒——他们想要确定他们所做的动作有时间产生效果。

但这不是应该做的。我们的3步理论适用于任何抓取场景:应该等待的是想要操作的特定DOM元素。它更快、更清晰,如果出了问题,会得到更准确的错误提示。

await tab.open("https://www.facebook.com/phbuster/posts/676836339178597")
// await Promise.delay(5000) // DON'T DO THIS!
await tab.waitUntilVisible(".permalinkPost .UFILikeLink")
// You can now safely click the "Like" button...
await tab.click(".permalinkPost .UFILikeLink")

在某些情况下,可能的确有必要伪造人为的延迟。可以使用

await Promise.delay(2000 + Math.random() * 3000)

糊弄过去。

MongoDB

我们发现MongoDB很适合大部分的抓取工作,它有一套优秀的JS API和Mongoose ORM。考虑到当使用Headless Chrome时已经处于NodeJS环境中,为什么不采用它呢?

JSON-LD 和微数据开发

有时网页抓取并不需要理解DOM,而是要找到正确的“导出”按钮。记住这一点可以节省了不少时间。

严谨的说有些网站会比其他网站容易一些,以Macys.com为例,他们所有的产品页面都以JSON-LD形式的产品数据显示在DOM中。可以说到它们的任何一个产品页面然后运行

JSON.parse(document . queryselector(" # productSEOData "). innertext)

将得到一个可以插入MongoDB很好的数据对象,没有真正抓取的必要!

网络请求拦截


image

因为使用的是DevTools API,所以编写的代码具有使用Chrome的DevTools的等效功能。这意味着产生的机器人可以拦截、检查甚至修改或中止任何网络请求。

通过从LinkedIn下载PDF格式的简历来测试网络请求拦截。从配置文件中单击“Save to PDF”按钮触发XHR,其中响应内容为PDF文件,这是一种拦截文件并将其写入磁盘的方法。

let cvRequestId = null
tab.driver.client.Network.responseReceived((e) => {if (e.type === "XHR" && e.response.url.indexOf("profile-profilePdf/") > 0) {cvRequestId = e.requestId}
})
tab.driver.client.Network.loadingFinished((e) => {if (e.requestId === cvRequestId) {tab.driver.client.Network.getResponseBody({ requestId: cvRequestId }, (err, cv) => {require("fs").writeFileSync("linkedin-cv.pdf", Buffer.from(cv.body, (cv.base64Encoded ? 'base64' : 'utf8')))})}
})

值得一提的是DevTools协议正在迅速发展,现在有一种方法可以使用Page.setDownloadBehavior()设置下载传入文件的方式和路径。我们还没有测试它,但看起来很有前途!

广告拦截
const nick = new Nick({loadImages: false,whitelist: [/.*\.aspx/,/.*axd.*/,/.*\.html.*/,/.*\.js.*/],blacklist: [/.*fsispin360\.js/,/.*fsitouchzoom\.js/,/.*\.ashx.*/,/.*google.*/]
})

同样可以通过屏蔽不必要的请求来加速抓取,分析、广告和图片是典型的屏蔽目标。然而,谨记它会让机器人变得不那么像人(例如,如果屏蔽了所有的图片,领英就不会正确响应页面请求——不确定这是否是故意的)。

在NickJS中用户可以指定一个白名单和一个包含正则表达式或字符串的黑名单。白名单特别强大,但如果不小心的话,很容易让目标网站崩溃。

DevTools协议也有Network.setBlockedURLs(),它使用带有通配符的字符串数组作为输入。

更重要的是,新版本的Chrome将带有谷歌自带的“广告拦截器”——它更像是一个广告“过滤器”。协议已经有一个端点叫做Page.setAdBlockingEnabled()。

这就是我们说的技巧!

Headless Chrome检测

最近发表的一篇文章列举了多种方法来检测Headless Chrome访问者,也有可能检测PhantomJS。那些方法描述了从基本的User-Agent字符串比较到更复杂的诸如触发错误和检查堆栈跟踪的技术。

在愤怒的管理员和巧妙的机器人制造商之间,这基本上是一个加大版的猫捉老鼠游戏。但从未见过这些方法在官方实施。在技术上是可以检测到自动访问者,但谁会愿意面对潜在的错误消息呢?对于大型的网站来说尤其有风险。

如果你知道那些网站有这些检测功能,请告诉我们!

结束语

抓取从来没有这么容易过,有了我们最新的工具和技术,它甚至可以成为我们开发人员愉快而有趣的活动。

顺便说一下,我们从Franciskim.co“我不需要臭烘烘的API”文章中受到了启发,非常感谢!另外,关于了解怎样开始使用木偶的详细说明,请点击这里。

在下一篇文章中,将写到关于“bot mitigation”的工具,比如Distill Networks,讲述HTTP代理和IP地址分配的美妙世界。

在Phantombuster.com上有我们的抓取和自动化平台 NickJS.org库。有兴趣的话还可以了解我们的3个抓取步骤的理论信息。

这篇关于2017年网页抓取:先进的Headless Chrome技巧的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/200835

相关文章

ubuntu16.04如何部署dify? 在Linux上安装部署Dify的技巧

《ubuntu16.04如何部署dify?在Linux上安装部署Dify的技巧》随着云计算和容器技术的快速发展,Docker已经成为现代软件开发和部署的重要工具之一,Dify作为一款优秀的云原生应用... Dify 是一个基于 docker 的工作流管理工具,旨在简化机器学习和数据科学领域的多步骤工作流。它

Python Selenium动态渲染页面和抓取的使用指南

《PythonSelenium动态渲染页面和抓取的使用指南》在Web数据采集领域,动态渲染页面已成为现代网站的主流形式,本文将从技术原理,环境配置,核心功能系统讲解Selenium在Python动态... 目录一、Selenium技术架构解析二、环境搭建与基础配置1. 组件安装2. 驱动配置3. 基础操作模

MySQL复合查询从基础到多表关联与高级技巧全解析

《MySQL复合查询从基础到多表关联与高级技巧全解析》本文主要讲解了在MySQL中的复合查询,下面是关于本文章所需要数据的建表语句,感兴趣的朋友跟随小编一起看看吧... 目录前言:1.基本查询回顾:1.1.查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J1.2.按照部门

Python中Flask模板的使用与高级技巧详解

《Python中Flask模板的使用与高级技巧详解》在Web开发中,直接将HTML代码写在Python文件中会导致诸多问题,Flask内置了Jinja2模板引擎,完美解决了这些问题,下面我们就来看看F... 目录一、模板渲染基础1.1 为什么需要模板引擎1.2 第一个模板渲染示例1.3 模板渲染原理二、模板

Pandas利用主表更新子表指定列小技巧

《Pandas利用主表更新子表指定列小技巧》本文主要介绍了Pandas利用主表更新子表指定列小技巧,通过创建主表和子表的DataFrame对象,并使用映射字典进行数据关联和更新,实现了从主表到子表的同... 目录一、前言二、基本案例1. 创建主表数据2. 创建映射字典3. 创建子表数据4. 更新子表的 zb

一文教你Python如何快速精准抓取网页数据

《一文教你Python如何快速精准抓取网页数据》这篇文章主要为大家详细介绍了如何利用Python实现快速精准抓取网页数据,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录1. 准备工作2. 基础爬虫实现3. 高级功能扩展3.1 抓取文章详情3.2 保存数据到文件4. 完整示例

快速修复一个Panic的Linux内核的技巧

《快速修复一个Panic的Linux内核的技巧》Linux系统中运行了不当的mkinitcpio操作导致内核文件不能正常工作,重启的时候,内核启动中止于Panic状态,该怎么解决这个问题呢?下面我们就... 感谢China编程(www.chinasem.cn)网友 鸢一雨音 的投稿写这篇文章是有原因的。为了配置完

python获取网页表格的多种方法汇总

《python获取网页表格的多种方法汇总》我们在网页上看到很多的表格,如果要获取里面的数据或者转化成其他格式,就需要将表格获取下来并进行整理,在Python中,获取网页表格的方法有多种,下面就跟随小编... 目录1. 使用Pandas的read_html2. 使用BeautifulSoup和pandas3.

Python ZIP文件操作技巧详解

《PythonZIP文件操作技巧详解》在数据处理和系统开发中,ZIP文件操作是开发者必须掌握的核心技能,Python标准库提供的zipfile模块以简洁的API和跨平台特性,成为处理ZIP文件的首选... 目录一、ZIP文件操作基础三板斧1.1 创建压缩包1.2 解压操作1.3 文件遍历与信息获取二、进阶技

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字