Apify与移动代理:从零到云端的逐步指南
前言
在本逐步指南中,您将设置完整的云端网页抓取,使用移动代理,创建一个Node.js演员,运行商品卡片抓取的测试任务,并学习如何安全管理限额,以避免错误和封锁。该指南面向初学者,但包括适合进阶用户的部分。最后,您将拥有一个可重复使用的演员、有效的代理设置、结果检查、清单、常见错误分析和优化建议。如有需要,您可以扩展项目,添加调度程序、导出到Google Sheets、API集成和监控。如果您有具体问题需要快速解答,请直接转到FAQ部分,但要获取完整的结果,请务必按照所有步骤进行。
本指南适合那些想要了解如何启动Apify演员并使用移动代理的人,不必花费数周时间研究文档。对营销人员、分析师、研究人员、在线项目拥有者和需要可靠、可重复的数据抓取的初学开发者都将非常有用。
需要事先了解的内容:基本的JavaScript概念会很有帮助,但不是必要的。我们会详细说明该点击哪里、输入什么以及如何检查结果。重要的是能在网上服务中登录、复制访问令牌,并小心处理密码。
所需时间:整个过程需要2-3小时,包括注册、设置演员、集成代理、测试启动和结果检查。如果您已经有Apify帐户和移动代理访问权限,通常可以在60-90分钟内完成。
预备工作
所需工具、程序和访问权限
- 具有启动演员权限的Apify帐户。
- 本地计算机上的LTS版本Node.js(18或更高),如果您想在本地编辑代码。可以使用Apify内置的编辑器,但本地工作更为方便。
- 移动代理的凭据。以mobileproxy.space为例,您可以获取登录名、密码和代理服务器地址。您可以使用任何类似的服务。
- 文本编辑器:VS Code或其他编辑器。
- Apify CLI(可选),用于本地开发和将演员上传到云。
系统需求
- 稳定的互联网访问。
- Windows、macOS或Linux。对于本地工作,只需一台现代计算机即可。
- 空闲的200-500MB磁盘空间用于npm依赖项的安装,如果采用本地开发。
需要下载和安装的内容
- 从官方网站安装Node.js,选择LTS版本。安装后,使用以下命令在终端检查:node -v和npm -v。您应该看到没有错误的版本。
- 使用命令安装Apify CLI(可选):npm i -g apify-cli。安装后检查:apify --version。
- 准备移动代理的凭据:主机、端口、登录名和密码。如果使用mobileproxy.space,您将获得类似host:port的地址以及user:password的组合。
⚠️ 注意:永远不要在公开的存储库中发布代理的登录名和密码。请使用环境变量或平台的机密管理功能。
备份创建
如果您在本地编辑代码,请保持项目的备份(例如,使用git)。在Apify平台上,会自动保存演员的版本,但最好还是有本地代码的备份。
建议:如果您第一次使用Apify,请直接通过平台界面中的编辑器开始,而以后再加入本地开发。这将加快启动速度。
基本概念及Apify简介
简单语言解释的关键术语
- Apify—用于网页自动化的平台:抓取、爬虫、集成。允许在云中运行代码(演员),存储结果(数据集)并管理链接队列。
- 演员—一个容器化的应用程序(通常为Node.js或Python),执行您的任务:打开页面、收集数据、存储结果。
- 任务(Task)—保存的演员启动配置,配有预填的输入。适合定期重启,而无需更改代码。
- 数据集(Dataset)—以表格形式存储抓取结果。可以导出为JSON、CSV、XLSX。
- 键值存储(Key-Value Store)—存储任意文件和配置(例如输入参数、报告)。
- 请求队列(Request Queue)—用于爬虫的链接队列,以系统方式存储和处理URL。
- 代理配置(ProxyConfiguration)—代理的配置。可以使用Apify代理或外部代理,包括移动代理。
- 移动代理—使用移动运营商网络的代理。它们通常被网站视为真实的移动流量。
工作原理的主要原则
您编写演员,传递输入参数并在云中启动。演员获取链接列表,通过选择的爬虫打开链接(例如,对于简单HTML页面的CheerioCrawler或用于复杂网站的PlaywrightCrawler),收集数据并写入数据集中。对于网络请求,演员根据代理配置使用代理。当需要低误报率的稳定收集时,采用移动代理。它们可以分散负载,并让目标看起来像是移动用户。
开始之前需要了解的重要事项
- 遵循目标网站的规则和现行法律。请以道德和合法的方式进行数据收集。
- 即使是移动代理也不能保证免受限制。请求的频率、延迟、正确的HTTP头以及爬虫的代码质量都十分重要。
- Apify平台和您的定价计划的限制,会影响并发、内存和执行时间。这是可以设置和控制的。
建议:如果目标提供官方API,请从API开始。这比解析HTML更稳定、道德。
步骤1:在云抓取中使用移动代理的目的
阶段目标
理解在何种情况下移动代理能够取得最佳效果,以及如何调整设置,以在云工作时减少封锁和不稳定性。
详细的逐步指南
- 确定数据收集的目的:商品列表、价格、评论、时间表、新闻。记录具体的页面类型及其大致URL。
- 评估网站的复杂性:页面是否可以在没有JavaScript的情况下打开,加载速度如何,是否有动态加载。如果网站简单,使用CheerioCrawler就足够了;如果复杂,则使用PlaywrightCrawler。
- 确定是否需要移动会话:如果网站明显面向移动用户,为移动和桌面客户显示不同版本的页面,移动代理将有助于显得更自然。
- 选择移动代理提供商。以mobileproxy.space为例,确保您拥有稳定的主机、端口、登录名和密码。将它们单独记录。
- 规划请求频率。开始时使用1-2个并发选项和1-3个请求每秒。必要时逐步增加,观察错误和网站的反馈。
- 决定是否使用IP轮换。对于移动代理,轮换可以顺应命令或通过提供商的计时器进行。确认您的提供商的政策和轮换命令。
关键点
移动代理在需要降低误报保护的可能性或者重现移动客户行为时非常合适。请勿将其用于被网站或法律禁止的行为。请正确设置User-Agent头和延迟。
⚠️ 注意:请勿尝试绕过网站的技术限制。如果页面因授权或使用条款而被封,请遵循资源的规则。
预期结果
您明白为什么使用移动代理,已经选择了提供商,并准备好在演员中进行设置。您拥有代理的凭据和请求频率的计划。
可能的问题及解决方案
- 不清楚是否需要移动版本。解决方案:在开发者浏览器中使用移动User-Agent打开该网站,并比较页面结构。如果差异明显,移动会话是合适的。
- 对提供商的可靠性存疑。解决方案:通过curl与您的代理测试连接,检查10-15分钟的稳定性。
✅ 检查:您已确切获得代理参数(主机、端口、登录名、密码)并记录了所需的请求频率。
步骤2:在Apify注册并准备工作空间
阶段目标
创建或确认Apify帐户,登录控制台,必要时安装Apify CLI,并准备创建演员。
详细的逐步指南
- 在Apify注册。输入电子邮件,设定密码,确认电子邮件。在登录后,将打开包含Actors、Tasks、Storage部分的控制台。
- 访问个人资料并找到您的个人API令牌。将其复制到安全的地方,它将在CLI和集成中使用。
- 如果使用CLI:使用命令npm i -g apify-cli安装apify-cli。然后执行apify login并粘贴令牌。成功登录后,您将看到终端的确认信息。
- 如果您选择本地开发,请创建项目的工作文件夹。执行apify create并选择基于Node.js的Crawlee模板。将创建项目结构,包括package.json和src/main.js。
- 如果您只是通过浏览器工作:在Actors部分中点击New并选择Node.js + Crawlee模板。平台将创建一个空演员并打开在线编辑器。
关键点
令牌的安全性至关重要。请不要将令牌粘贴到代码中。将其存储在密码管理器中。在CLI中,它会被本地保存,除非您手动添加到存储库中。
建议:给演员取个有意义的名字,例如mobile-crawler-products。这将简化导航和自动化。
预期结果
您已登录Apify控制台,如果需要已设置CLI,创建了一个空演员,并在编辑器中看到main.js文件(或在src文件夹中本地看到)。
可能的问题及解决方案
- CLI无法找到令牌。解决方案:运行apify logout并重新运行apify login。检查您输入的令牌是否仍然有效。
- npm依赖项安装错误。解决方案:将Node.js更新到LTS版本,使用npm cache clean --force清除npm缓存,并重试安装。
✅ 检查:您已创建了可编辑代码的演员,并且基本项目结构已到位。
步骤3:创建演员并上传模板
阶段目标
为演员填充初始Crawlee代码,以便可以立即启动爬虫并确保基本功能正常,无需代理。
详细的逐步指南
- 打开main.js文件。如果没有,请创建src/main.js。确保package.json包含crawlee和apify的依赖项。
- 插入基础爬虫代码。CheerioCrawler的示例:import { CheerioCrawler, Dataset } from "crawlee"; export const main = async () => { const startUrls = ["https://example.com/"]; const crawler = new CheerioCrawler({ requestHandler: async ({ request, $, log }) => { const title = $("title").text(); await Dataset.pushData({ url: request.loadedUrl, title }); log.info(`Saved: ${request.loadedUrl}`); }, maxConcurrency: 2, requestHandlerTimeoutSecs: 60, }); for (const url of startUrls) await crawler.addRequests([url]); await crawler.run(); };
- 保存文件。如果在浏览器中,请单击保存按钮。如果在本地,请保存更改并运行npm install以获取库(如果还未获取)。
- 尝试无代理运行:使用默认输入启动演员。数据集中应至少出现一个带有title字段的对象。
关键点
至少的MVP演员是用来检查管道的:启动、日志记录和保存结果。在添加代理之前,确保代码能在简单页面上正常运行。
建议:从一两个启动链接开始。这将加快测试速度并简化问题的查找。
预期结果
演员成功启动并将结果保存到数据集中。您可以在日志中看到确认数据已保存,并且没有DNS或网络超时等错误。
可能的问题及解决方案
- 导入包时出错。解决方案:检查package.json中的版本。如果需要,请运行npm i crawlee apify。
- 数据集没有数据。解决方案:检查选择器$("title").text()或将其替换为其他简单选择,例如$("h1").first().text()。
✅ 检查:数据集中至少有一个带有url和title字段的对象。日志显示成功结束,未发生异常。
步骤4:在演员中设置代理
阶段目标
将移动代理连接到Apify的演员,以便爬虫的所有网络流量都通过指定的代理服务器,同时确保连接的稳定性。
详细的逐步指南
- 准备代理字符串。外部HTTP代理格式为:http://USERNAME:PASSWORD@HOST:PORT。示例:http://user123:pass456@proxy.mobileproxy.space:12345。对于mobileproxy.space,请使用来自个人帐户的凭据。
- 在代码中添加ProxyConfiguration。对于CheerioCrawler:import { CheerioCrawler, Dataset, ProxyConfiguration } from "crawlee"; export const main = async () => { const proxy = new ProxyConfiguration({ proxyUrls: ["http://USERNAME:PASSWORD@HOST:PORT"] }); const crawler = new CheerioCrawler({ proxyConfiguration: proxy, requestHandler: async ({ request, $, log }) => { const title = $("title").text(); await Dataset.pushData({ url: request.loadedUrl, title }); log.info(`Saved: ${request.loadedUrl}`); }, maxConcurrency: 2, requestHandlerTimeoutSecs: 60, }); await crawler.addRequests(["https://httpbin.org/ip"]); await crawler.run(); };
- 保存更改并启动演员。如果一切正常,数据集中将显示您移动代理的IP地址(对于httpbin.org/ip,将显示带有origin或代理IP的JSON)。
- 如果使用PlaywrightCrawler,请将相同的ProxyConfiguration添加到构造函数的参数中:import { PlaywrightCrawler, Dataset, ProxyConfiguration } from "crawlee"; const proxy = new ProxyConfiguration({ proxyUrls: ["http://USERNAME:PASSWORD@HOST:PORT"] }); const crawler = new PlaywrightCrawler({ proxyConfiguration: proxy, launchContext: { launchOptions: { headless: true } }, requestHandler: async ({ page, request, log }) => { const title = await page.title(); await Dataset.pushData({ url: request.loadedUrl, title }); log.info(`Saved: ${request.loadedUrl}`); } });
- 如有必要,可以将代理字符串提取到环境变量中,并通过process.env读取,以便不在代码中存储密码。在Apify平台上使用演员设置中的Secrets和ENV Vars部分。示例:const proxyUrl = process.env.MOBILE_PROXY_URL;
关键点
不要混合同时使用Apify代理和外部移动代理配置。在一次执行中使用一个清晰的代理来源。通过proxyUrls进行的设置完全取代了使用Apify代理。
建议:首先在简单页面上测试代理,例如https://httpbin.org/ip或类似IP显示服务。这样你会立即确认流量通过了正确的地址。
⚠️ 注意:如果移动代理提供商支持通过专用URL或命令进行IP轮换,请仅在其规则范围内使用。没有必要时,请不要过于频繁地更换IP:这可能会引起目标网站的怀疑。
预期结果
爬虫成功连接到移动代理。检查IP(通过测试页面)时,您会看到代理地址,日志稳定,请求未超时。
可能的问题及解决方案
- 日志中出现401或407。原因:登录名或密码错误。解决办法:检查提供商个人帐户中的凭据。
- 出现ECONNRESET或ETIMEDOUT。原因:连接不稳定或域被阻挡。解决方案:减少并发,稍作暂停后重新启动,检查提供商处的代理状态。
✅ 检查:数据集包含对显示IP的页面请求的结果,并且可以看到移动代理的地址。
步骤5:示例任务:从商品卡片收集数据
阶段目标
从实际商品卡片收集数据,使用移动代理和稳定的爬虫设置,并将结果保存到数据集中。
详细的逐步指南
- 确定目标URL列表或类别,以安全和合法地收集开放数据。记录3-5个链接用于测试。
- 选择爬虫。如果页面是静态的,使用CheerioCrawler。如果数据是动态加载的,选择PlaywrightCrawler。
- 添加主要的选择器以提取数据。例如:商品名称、价格、货币、评分、库存。在Cheerio中这些将是类似于jQuery的选择器;在Playwright中则使用page.locator。
- CheerioCrawler的示例:import { CheerioCrawler, Dataset, ProxyConfiguration, log } from "crawlee"; export const main = async () => { log.setLevel(log.LEVELS.INFO); const proxy = new ProxyConfiguration({ proxyUrls: [process.env.MOBILE_PROXY_URL] }); const startUrls = ["https://example.com/product/1", "https://example.com/product/2"]; const crawler = new CheerioCrawler({ proxyConfiguration: proxy, maxConcurrency: 2, requestHandlerTimeoutSecs: 90, requestHandler: async ({ request, $, log }) => { const title = $("h1.product-title").text().trim(); const priceText = $("span.price").text().trim(); const availability = $("div.stock").text().trim(); const currency = priceText.replace(/[0-9.,\s]/g, ""); const price = parseFloat(priceText.replace(/[^0-9.,]/g, "").replace(",", ".")) || null; await Dataset.pushData({ url: request.loadedUrl, title, price, currency, availability }); log.info(`Saved: ${title || "no title"}`); }, failedRequestHandler: async ({ request, log }) => { log.warning(`Failed ${request.url}`); } }); await crawler.addRequests(startUrls); await crawler.run(); };
- PlaywrightCrawler的示例:import { PlaywrightCrawler, Dataset, ProxyConfiguration } from "crawlee"; export const main = async () => { const proxy = new ProxyConfiguration({ proxyUrls: [process.env.MOBILE_PROXY_URL] }); const startUrls = ["https://example.com/product/1"]; const crawler = new PlaywrightCrawler({ proxyConfiguration: proxy, requestHandlerTimeoutSecs: 120, launchContext: { launchOptions: { headless: true } }, requestHandler: async ({ page, request, log }) => { await page.waitForLoadState("domcontentloaded"); const title = await page.title(); const price = await page.locator("span.price").first().textContent().catch(() => null); await Dataset.pushData({ url: request.loadedUrl, title, price }); log.info(`Saved: ${request.loadedUrl}`); } }); await crawler.addRequests(startUrls); await crawler.run(); };
- 将MOBILE_PROXY_URL保存在Apify平台演员的环境变量中(设置→环境变量部分)。值为:您的代理字符串http://user:pass@host:port。
- 启动演员。在日志中,您应监控请求状态、响应时间以及成功保存的记录数。
关键点
数据集中的数据结构应可预测:为所有卡片设置相同的字段,否则导出到表格将不方便。控制超时:对于动态页面,请增加requestHandlerTimeoutSecs,并在关键选择器上添加等待。
建议:为平滑负载,在请求之间添加300-1500毫秒的小延迟。这样显得更自然,并降低被限制的风险。
预期结果
数据集中包含每个商品卡片的记录,具有关键字段。日志稳定,不存在授权代理的错误,平均响应时间对您的案例来说合理。
可能的问题及解决方案
- 选择器不正确。原因:响应式布局或页面结构不同。解决方案:检查移动和桌面版本,使用更稳定的选择器(数据属性、唯一ID)。
- 某些字段为空。原因:值动态加载。解决方案:添加对所需元素的明确等待,或者使用Playwright而不是Cheerio。
✅ 检查:数据集中存在带有url、title、price或等效字段的记录。错误的平均百分比较低,测试样本中低于5-10%。
步骤6:限制与优化
阶段目标
配置并发、超时、重试、轮换和存储,以节省Apify的配额并提高收集的稳定性。
详细的逐步指南
- 限制并发性。在爬虫参数中设置maxConcurrency,起初设置为1到3。逐步增加。并发越高,代理和网站的负担也越大。
- 设置重试。在Crawlee中有retryCount和retryTimeoutMillis。设置retryCount = 1-2,以免无限期地对问题页面进行请求。
- 管理执行时间。对于较重的页面,将requestHandlerTimeoutSecs提升到90-120。这将减少由于移动网络缓慢响应而产生的错误超时。
- 添加随机延迟。在请求之间插入小暂停300-1500毫秒。这显得更自然,减少了被限制的风险。
- 合理规划提供商的代理轮换。如果mobileproxy.space允许按计时器请求新IP,请选择不破坏会话稳定性的时间间隔。
- 监控Apify的限制:内存、CPU、时间。在启动设置中指定Memory(例如,Playwright的1024-2048 MB)以及Max run time(例如,批处理的30-60分钟)。
- 仅存储必要字段。数据集中冗余数据越少,存储负担越轻,导出速度越快。去掉无必要的HTML片段。
- 在DEBUG模式下开启适当的日志记录。过多的日志可能会干扰阅读,而在稳定模式下并不需要。
关键点
节省配额可以通过一些简单的规则实现:低初始并发、短重试时间、准确的选择器和最小化不必要的页面请求。监控通过日志和监控帮助调整设置。
建议:将成功的URL保存到键值存储或外部存储中。这将简化从故障处恢复的过程,并避免重复处理已经收集的页面。
预期结果
演员平稳运行,未消耗多余资源,且错误出现的频率低且可预测。超时和并发的参数经过调整,以符合您的移动代理速度和网站的复杂性。
可能的问题及解决方案
- 增加超时没有帮助。原因:页面过载或提供商问题。解决方案:暂时将并发降低到1,并检查连接的稳定性。
- 速度太慢。原因:代理网络的瓶颈或网站较重。解决方案:增加延迟,同时考虑将任务拆分为更小的批次。
✅ 检查:每页的平均处理时间稳定,错误百分比在增加量不变的情况下并未增加,内存和时间限制未被超过。
结果检查
清单:应正常工作的内容
- 演员可以启动且无错误,并正确地完成工作。
- 移动代理已连接,检查请求中的IP与代理一致。
- 数据集包含预期的字段和值。
- 日志内容充实,但没有过载。
- 再次启动时没有多余重复记录(或者它们是可以控制的)。
如何进行测试
- 在2-3个测试URL上运行演员,启用代理,并通过IP指示页面检查IP。
- 比较数字:添加了多少请求和得到了多少结果。它们应该一致,或者在可理解的误差范围内。
- 将数据集导出为CSV,并确保数据干净:期望值无null。
成功执行的指标
- 失败请求的百分比低于5-10%。
- 每页的平均处理时间稳定且可预测。
- 没有异常的超时和代理授权错误。
建议:在每次重大代码更改前,记录控制的URL集合并重复测试。这样您可以快速捕捉回归。
典型错误及解决方案
- 问题:407 Proxy Authentication Required。原因:代理凭据错误。解决方案:检查登录名和密码,更新环境变量并重启演员。
- 问题:日志中的ECONNRESET和ETIMEDOUT。原因:网络不稳定或过载。解决方案:降低maxConcurrency,增加超时并在请求之间停顿。
- 问题:数据集中存在空白字段。原因:选择器错误或动态加载。解决方案:使用PlaywrightCrawler,添加等待,重审选择器。
- 问题:达到内存限制。原因:过多并发标签或存储冗余数据。解决方案:降低并发,减少数据量,增加启动设置中的Memory。
- 问题:抓取速度过慢。原因:页面复杂和移动网络。解决方案:确定数据的重要性队列,将任务拆分为批处理,优化选择器,关闭无谓的导航。
- 问题:结果中存在重复。原因:使用相同的URL重复执行而没有过滤。解决方案:在Request Queue中维护已处理链接的列表以进行唯一性检查,或在保存前检查重复。
- 问题:敏感网站对频繁请求做出反应。原因:请求节奏过于激进。解决方案:降低请求速度,增加延迟的抖动,使用正确的头和当前的User-Agent。
建议:调试时,临时为一两个URL打开详细日志,以分析每一步。这比处理长批量要更快。
额外功能
高级配置
- 机密和配置。将MOBILE_PROXY_URL和其他关键保存在Secrets部分。在代码中通过process.env读取。
- 更改User-Agent。为了模拟移动客户,请设置移动User-Agent及相应的viewport宽度在Playwright中。切勿过度使用,仅在确保页面正常显示的情况下才使用。
- 任务调度。创建任务并设置启动调度(每天、每小时)。监测您的配额和结果的量。
优化
- 缓存。如果页面鮮少更改,添加请求和重复访问的缓存,以免浪费代理和配额。
- 队列和优先级。通过Request Queue工作,给予重要链接的优先权,绕过次要链接。
- 拆分为微服务。将复杂任务拆分为几个演员:收集链接、处理卡片、验证和导出。
还有哪些事情可以做
- API集成。在每次运行后,通过Webhook将结果发送到您的CRM或分析系统。
- 数据验证。在导出前检查模式:以确保所有值符合预期类型和范围。
- 文档内部链接。如有必要,在调整性能时返回限制与优化部分。
建议:在调度中使用预览模式和小批量进行初步运行,然后逐渐扩展。
常见问题
- 如何判断代理是否确实是移动的?通过第三方数据库检查IP的ASN和网络类型,并与移动运营商进行比较。此外,移动代理通常具有动态变化的特征。
- 可以同时使用多个移动代理吗?可以,指定多个proxyUrls。Crawlee会自动从列表中选择一个。请监控每个代理的配额。
- 如果网站显示验证码该怎么办?降低频率,增加延迟,检查头信息,并考虑使用资源的官方API。避免违反网站规则的操作。
- 如何安全存储代理密码?使用平台Apify上的环境变量和Secrets。不要在git中提交密码。
- 是否需要将User-Agent更改为移动的?仅当网站返回不同的页面版本时。在其他情况下,稳定的行为和正确的延迟通常就足够了。
- 为什么CheerioCrawler更快?因为它不渲染页面,而是解析HTML。对于动态页面,请使用PlaywrightCrawler,尽管速度较慢。
- 如何导出结果?在数据集界面中选择导出为CSV、JSON、XLSX。或者使用Datasets API来自动化导出。
- 可以组合Apify Proxy和移动代理吗?在一次执行中最好只使用其中一个。如需不同来源,分隔任务按演员或启动配置进行。
- 每秒可以安全发送多少请求?从每秒1-3开始,实时跟踪指标。对于敏感网站,将频率降低到0.2-0.5并设置延迟。
- 在Playwright中启用headful模式是否有必要?仅用于调试。在生产中使用headless以节省资源。
结论
您已成功设置Apify的工作演员及移动代理,了解了关键概念和原理,从商品卡片收集了测试数据,并优化了配额。现在您可以自信地管理并发、超时和结果存储,并知道如何保护机密和密码。接下来,您可以扩展项目:添加新的页面类型,构建多个演员的管道,连接调度程序和自动导出。如果有具体的问题,请返回到FAQ部分或限制与优化部分。请记住,移动代理是提高稳定性和流量自然性的工具,而不是规避限制的方法。务必保持道德,遵循网站规则,并始终从小处做起,逐一验证每个更改。