返回博客
网络抓取科学
苏丘·丹2023年1月16日阅读时长 8 分钟

用于网络抓取的节点解锁程序

用于网络抓取的节点解锁程序

什么是 Node-Unblocker?

Node Unblocker 是一个通用库,用于创建 Web 代理,拦截并修改请求和响应。 

该库还常用于网络爬虫,以绕过网站实施的限制(如地理封锁、隐藏 IP 地址和速率限制),或用于发送认证令牌。 

简而言之,使用这个库后,你可以彻底告别被屏蔽和审查的内容。

在本文中,我们将使用 Node Unblocker 创建一个带有自定义代理的 Express 应用程序,添加一个用于修改每次请求的用户代理的中间件,探讨代理的局限性,将其部署到 Heroku,并将其与WebScrapingAPI 这样的托管服务进行比较。

先决条件

开始之前,请确保您已安装了最新版本的 Node.JS。关于在各平台(Windows、Linux、Mac)上安装 Node.JS 的具体方法,我们将另文详述,因此在此不再赘述,请访问官方网站并按照说明进行操作。

准备工作

首先,我们为项目创建一个名为 unblocked 的目录,并在其中初始化一个 Node.JS 项目:

mkdir unblocked
cd unblocked
npm init

安装依赖项

对于这个应用程序,我们将安装两个库:Express(一个面向 Node.JS 的极简框架)和 Node Unblocker。

npm install express unblocker

创建基础应用程序

创建 Express 应用

由于 node.unblocker 在 Express 实例中运行,因此我们需要在应用程序中配置“Hello World”示例。

创建一个 index.js 文件并粘贴以下代码:

const express = require('express')const app = express()const port = 8080  app.get('/', (req, res) => {    res.send('Hello World!')  })  app.listen(process.env.PORT || 8080, () => {    console.log(`示例应用正在监听端口 ${port}`)  })

我们可以使用以下命令运行该应用程序:

node index.js

如果访问http://localhost:8080,我们会看到一条“Hello World”的消息。这说明我们的应用程序已成功运行。

将 Node Unblocker 添加到 Express

现在是时候将 Node Unblock 库导入到我们的应用程序中了:

var Unblocker = require('unblocker')

我们创建一个 Node Unblocker 实例,并传入 proxy 参数。您可以在此处查看所有可用参数的完整列表。

var unblocker = new Unblocker({prefix: '/proxy/'})

我们将 Node Unblocker 库作为中间件注册到 Express 中,以便拦截请求:

app.use(unblocker)

我们更新了 Express 应用程序监听器,以支持 WebSockets:

app.listen(process.env.PORT || 8080, () => {     console.log(`示例应用正在监听端口 ${port}`) }).on('upgrade', unblocker.onUpgrade)

完成所有这些步骤后,我们的应用程序应呈现如下所示:

const express = require('express') const Unblocker = require('unblocker') const app = express() const port = 8080  const unblocker = new Unblocker({prefix: '/proxy/'})  app.use(unblocker)  app.get('/', (req, res) => {     res.send('Hello World!') })  app.listen(process.env.PORT || 8080, () => {     console.log(`Example app listening on port ${port}`) }).on('upgrade', unblocker.onUpgrade)

测试代理

重新启动应用程序,并在浏览器中访问以下网址:

http://localhost:8080/proxy/https://webscrapingapi.com

为了确保代理按预期工作,我们打开浏览器中的开发者工具,并查看“网络”选项卡。所有请求都应通过代理进行。

浏览器开发者工具的“网络”选项卡显示了针对代理/解锁端点的 HTTP 请求以及页面资源

对于代理可能抛出的任何问题,建议通过设置 DEBUG 环境变量来启用调试模式。请使用以下命令以调试模式启动代理:

DEBUG=unblocker:* node index.js

在生产环境中启用此功能绝非明智之举,因此我们仅将其保留在开发环境中。

使用中间件

Nodeunblocker 不仅是一个自定义代理解决方案,还允许通过中间件拦截和修改进出请求。

我们可以利用此功能,根据资源类型或域名阻止特定资源加载,修改用户代理,替换返回的内容,或在请求头中注入认证令牌。

可以在此处查看完整的示例列表。

首先,我们来创建一个用于设置自定义用户代理的中间件。创建一个名为 user-agent.js 的文件,并在其中添加以下代码:

module.exports = function(userAgent) {
    function setUserAgent(data) {
        data["headers"]["user-agent"] = userAgent
    }
    return setUserAgent
}

该函数通过 userAgent 参数接收自定义用户代理,并使用 setUserAgent 函数将其注册到 data 对象中。Node unblocked 会在每次请求时调用 setUserAgent 函数。

const userAgent = require('./user-agent')

我们设置了 requestMiddle参数,这样应该就没问题了。

const unblocker = new Unblocker({
    prefix: '/proxy/',
    requestMiddleware: [userAgent("nodeunblocker/1.5")]
})

我们的 index.js 文件应如下所示:

const express = require('express')
const Unblocker = require('unblocker')
const userAgent = require('./user-agent')
const app = express()
const port = 8080

const unblocker = new Unblocker({
    prefix: '/proxy/',
    requestMiddleware: [userAgent("nodeunblocker/1.5")]
})

app.use(unblocker)

app.get('/', (req, res) => {
    res.send('Hello World!')
})

app.listen(process.env.PORT || 8080, () => {
    console.log(`Example app listening on port ${port}`)
}).on('upgrade', unblocker.onUpgrade)

现在是时候检查我们的代码是否正常运行了。我们需要修改 node-unblocker 的 URL,以确保请求头已正确更新。 

重新启动应用程序,并在浏览器中打开以下网址:

http://localhost:8080/proxy/https://www.whatsmyua.info/

如果网站显示 nodeunblocker/1.5,说明我们的中间件正常工作。

我的“用户代理”页面上有一个文本框,其中包含用户代理字符串,并有一个“去”按钮

部署到 Heroku

代理服务器运行后,现在是时候将其部署到 Heroku 了。Heroku 是一个平台即服务(PaaS)平台,允许我们在云端全面创建、发布和管理应用程序。

请注意,并非所有服务商都允许在其基础设施上运行代理和网络爬虫应用。只要不忽略 robots.txt 中的规则,Heroku 便允许此类应用运行。

既然法律方面已经讨论完毕,让我们开始为项目部署做准备吧。

脚本与引擎

我们需要在 package.json 文件中设置启动脚本和引擎。

`engines` 属性告知 Heroku,我们需要在环境中安装最新版本的 Node.JS 16。当环境配置完成且应用程序准备就绪时,将执行启动脚本。

我们的 package.json 应该如下所示:

{
  "name": "unblocked",
  "version": "1.0.0",
  "main": "index.js",
  "engines": {
    "node": "16.x"
  },
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^4.18.1",
    "unblocker": "^2.3.0"
  }
}

Heroku 让 Node.JS 应用程序的部署变得轻松愉快。在进入下一节之前,请确保您已安装Heroku CLIGit工具。

登录与设置

请在本地终端中使用以下命令与 Heroku 进行身份验证:

Heroku 登录

运行以下命令创建一个新的 Heroku 应用程序:

heroku apps:create

该命令将返回应用的 ID 和一个 Git 仓库。让我们使用该 ID 来设置我们仓库的远程源:

git init
heroku git:remote -a [YOUR_APP_ID]

由于将 `node_modules` 文件夹纳入版本控制绝非明智之举,因此我们来创建一个 `.gitignore` 文件,并将该文件夹添加到其中。

部署

在代码投入生产环境前的最后一步,是提交代码并进行部署。让我们将所有文件添加到提交中,创建一个提交,并将主分支合并到 Heroku 分支中。

git add .
git commit -am "初始提交"
git push heroku master

几秒钟后,应用程序就会部署到 Heroku 上。恭喜!现在可以在浏览器中访问它,并确认其是否正常运行。

请使用以下 URL 结构来构建 Heroku URL:

[HEROKU_DYNO_URL]/proxy/https://webscrapingapi.com

如果您忘记或丢失了 Dyno URL,可以使用以下命令获取当前应用的相关信息:

Heroku 信息

局限性

虽然这个自定义代理的配置非常简单,但有一个限制:它仅适用于简单的网站,而对于复杂的任务则无法胜任。其中一些限制无法克服,需要使用其他库或第三方服务。

像 WebScrapingAPI 这样的托管服务不仅解决了上述所有限制,还增加了若干额外功能,例如自动破解验证码、住宅代理以及高级规避机制,以防止 Akamai、Cloudflare 和 Datadome 等服务检测到您的请求。 

在考虑将 Node Unblocker 用于生产环境项目之前,请先了解以下限制事项。

OAuth 问题

OAuth 是 Facebook、Google、YouTube、Instagram 和 Twitter 等现代网站首选的身份验证标准。任何使用 postMessage 的库都无法与 Node Unblocker 兼容,而正如您可能已经猜到的,OAuth 需要 postMessage 才能正常运行。

如果你愿意为了使用这个库而放弃57%的互联网流量,那就尽管把它添加到你的项目中吧。

复杂站点

YouTube、HBO Max、Roblox、Discord、Instagram 等网站无法正常访问,目前尚无发布新版本以修复这些网站访问问题的具体时间表。 

欢迎社区成员提交补丁来修复这些问题,但在有人创建拉取请求之前,您将无法从这些数据中抓取任何信息。

Cloudflare

Cloudflare 提供一项免费检测服务,该服务在所有账户中默认处于启用状态。我们的自定义代理服务器将在数秒内被检测到,随后屏幕上将显示一个验证码提示。

大约 80% 的网站使用 Cloudflare CDN。如果请求被验证码拦截,可能会导致你的爬虫无法继续运行。

维护

尽管设置自定义代理很简单,但后续的维护工作会带来巨大的负担,并使您无法专注于业务目标。

您将需要处理代理实例的运行、配置自动扩展基础设施、应对并发问题以及管理集群。这些工作不胜枚举。

结论

现在,您已经在 Heroku 上运行了一个 Web 代理,并且对如何配置、部署它以及其局限性有了充分的了解。如果您打算将其用于业余项目,Node Unblocker 是一个不错的选择。

但这些缺点以及社区支持不足,使得您无法将其用于任何生产环境中的应用程序。

WebScrapingAPI 这样的托管服务,不仅提供庞大的数据中心、移动和家庭代理池,还能通过单个参数实现地理位置模拟、修改请求头以及创建 Cookie,因此完全不受上述限制。

关于作者
Suciu Dan,WebScrapingAPI 联合创始人
Suciu Dan联合创始人

Suciu Dan 是 WebScrapingAPI 的联合创始人,他撰写了关于 Python 网络爬虫、Ruby 网络爬虫以及代理基础设施的实用指南,这些指南专为开发者而设计。

开始构建

准备好扩展您的数据收集规模了吗?

加入2,000多家企业,使用WebScrapingAPI在无需任何基础设施开销的情况下,以企业级规模提取网页数据。