手机网页抓取视频(如何快速入门HeadlessChrome进行网页抓取的经验(组图))

优采云 发布时间: 2022-02-11 14:07

  手机网页抓取视频(如何快速入门HeadlessChrome进行网页抓取的经验(组图))

  翻译:没有两个

  Headless Chrome 是 Chrome 浏览器的一种无界面形式,无需打开浏览器即可运行使用 Chrome 支持的所有功能的程序。与现代浏览器相比,Headless Chrome 更方便测试web应用、获取网站的截图、爬取信息等,也更贴近浏览器环境。下面我们来看看作者分享的使用 Headless Chrome 进行网页抓取的经验。

  PhantomJS 的开发已经停止,Headless Chrome 成为焦点,每个人都喜欢它,包括我们。现在,网络抓取是我们工作的重要组成部分,我们现在广泛使用 Headless Chrome。

  本文 文章 将向您展示如何快速开始使用 Headless Chrome 生态系统,并展示您从已经爬取数百万个网页中学到的东西。

  文章总结:

  1. 控制Chrome的库很多,大家可以根据自己的喜好选择。

  2. 使用 Headless Chrome 进行网页抓取很容易,尤其是在您掌握了以下技术之后。

  3. 可以检测到无头浏览器访问者,但没有人可以检测到。

  无头 Chrome 简介

  Headless Chrome 基于 Google Chrome 团队开发的 PhantomJS(QtWebKit 内核)。团队表示,将专注于该项目的研发,并将在未来继续维护。

  这意味着对于网络抓取和自动化需求,您现在可以体验 Chrome 的速度和强大功能,因为它具有世界上最常用的浏览器的特性:支持所有 网站,支持 JS 引擎,并且很棒开发者工具 API。这太糟糕了!

  使用哪个工具来控制 Headless Chrome?

  

  市面上确实有很多 NodeJS 库支持 Chrome 新的 headless 模式,每个都有自己的特点。我们自己的是 NickJS。如果你没有自己的爬虫库,还敢说你是爬虫高手。

  还有一组由社区发布的其他语言的库,例如基于 GO 语言的库。我们建议使用 NodeJS 工具,因为它与 Web 解析语言相同(下面您将看到它有多方便)。

  网页抓取?这不是违法的吗?

  我们无意展开无休止的辩论,但不到两周前,一名美国地方法官命令第三方抓取公共 LinkedIn *敏*感*词*。到目前为止,这是一项初步法令,诉讼将继续进行,LinkedIn 肯定会反对,但不要担心,我们会密切关注情况,因为在这个 文章 中有很多关于 LinkedIn 的内容。

  无论如何,作为技术 文章,我们不会深入研究特定抓取操作的合法性,我们应该始终努力尊重目标 网站 的 ToS。并且对您在此 文章 中学到的任何损害不承担任何责任。

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

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

  把饼干放回饼干罐

  使用功能齐全的浏览器进行抓取可以让您高枕无忧,无需担心 CORS、会话、cookie、CSRF 和其他 Web 问题。

  但有时登录表单变得非常困难,唯一的解决方案是恢复以前保存的会话 cookie。一些网站在检测到故障时会发送电子邮件或短信。我们没有时间这样做,只需打开已设置会话 cookie 的页面即可。

  LinkedIn 有一个很好的例子,设置 li_atcookie 可以保证爬虫访问他们的社交网络(记住:注意尊重目标 网站Tos)。

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

  相信像 LinkedIn 这样的 网站 不会阻止具有有效会话 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 tool const data = [] $(".athing").each((index, element) => { data.push({ title: $(element).find(".storylink").text(), url: $(element).find(".storylink").attr("href") }) }) callback(null, data) })

  印度、*敏*感*词*和巴基斯坦在阻止机器人方面有什么共同点?

  

  答案是使用验证码来解决服务器验证。几块钱就可以买到几千个验证码,生成一个验证码通常不到30秒。但是晚上,因为没有人,所以一般比较贵。

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

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

  在我们的平台上,用户可以轻松解决他们需要的验证码问题。我们的 Buster 库可以:

  if (await tab.isVisible(".captchaImage")) { // Get the URL of the generated CAPTCHA image // Note that we could also get its -encoded value and solve it too const captchaImageLink = await tab.evaluate((arg, callback) => { callback(null, $(".captchaImage").attr("src")) }) // Make a call to a CAPTCHA solving service const captchaAnswer = await buster.solveCaptchaImage(captchaImageLink) // Fill the form with our solution await tab.fill(".captchaForm", { "captcha-answer": captchaAnswer }, { submit: true }) }

  等待一个 DOM 元素,而不是固定的时间

  通常会看到爬虫初学者让他们的机器人在打开页面或单击按钮后等待 5 到 10 秒——他们希望确保他们所做的操作有时间产生效果。

  但这不是应该做的。我们的三步理论适用于任何抓取场景:应该等待的是您想要操作的特定 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,而是要找到正确的“导出”按钮。记住这一点可以节省很多时间。

  严格来说,有些网站 比其他网站 更容易,例如,他们所有的产品页面都显示在 DOM 中,产品数据为 JSON-LD 格式。可以对他们的任何产品页面说,然后运行

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

  将得到一个可以很好地插入 MongoDB 的数据对象,无需真正的抓取!

  网络请求拦截

  

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

  通过从 LinkedIn 下载 PDF 格式的简历来测试 Web 请求拦截。单击配置文件中的“保存到 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.Encoded ? '' : 'utf8'))) }) } })

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

  广告拦截

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

  它还可以通过阻止不必要的请求来加快爬网速度。分析、广告和图片是典型的屏蔽目标。但是,请记住,它会使机器人变得不像人类(例如,如果所有图像都被阻止,LinkedIn 将无法正确响应页面请求 - 不确定这是否是故意的)。

  在 NickJS 中,用户可以指定收录正则表达式或字符串的白名单和黑名单。白名单功能特别强大,但如果您不小心,很容易使目标 网站 崩溃。

  DevTools 协议还有 Network.setBlockedURLs() ,它接受一个带有通配符的字符串数组作为输入。

  更重要的是,新版 Chrome 将带有谷歌自己的“广告*敏*感*词*”——它更像是一个广告“过滤器”。该协议已经有一个名为 Page.setAdBlockingEnabled() 的端点。

  也就是我们所说的套路!

  无头 Chrome 检测

  最近的一篇文章 文章 列举了检测 Headless Chrome 访问者以及可能还有 PhantomJS 的各种方法。这些方法描述了从基本的用户代理字符串比较到更复杂的技术(例如触发错误和检查堆栈跟踪)的所有内容。

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

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

  结束语

  抓取从未如此简单,借助我们最新的工具和技术,它甚至可以成为我们开发人员的一项愉快而有趣的活动。

  顺便说一句,我们的灵感来自 Franciskim.co “我不需要臭 API”文章,非常感谢!此外,有关如何开始使用木偶的详细说明,请单击此处。

  在下一篇文章中,文章,我将写关于“机器人缓解”工具,比如 Distill Networks,关于 HTTP 代理和 IP 地址分配的美妙世界。

  上有一个我们的抓取和自动化平台的库。如果您有兴趣,还可以了解我们的 3 个抓取步骤的理论信息。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线