尽管到目前为止本指南看起来似乎轻而易举,但网络爬虫通常会遇到多种挑战。尤其是 YouTube,它实施了许多反机器人技术来防止自动化脚本提取其数据。
其中一些技术包括:
- 验证码(CAPTCHA):对爬虫而言,破解验证码既费时又困难,这本身就能起到阻止机器人的作用。
- JavaScript 验证:可能包含解决数学题、完成 CAPTCHA 或在页面上查找特定元素等任务。无法完成验证的机器人会被检测到并可能遭到封锁。
- 用户代理检查:YouTube 可能会检查传入请求的用户代理字符串,以判断其来源是浏览器还是爬虫。如果用户代理字符串未被识别为有效的浏览器,该请求可能会被拦截。
- IP 封禁:YouTube 可能会封禁来自已知与机器人或抓取活动相关的特定 IP 地址的请求。
- 蜜罐:YouTube 可能会使用蜜罐,即页面上仅对机器人可见的隐藏元素。如果检测到机器人与蜜罐进行交互,即可将其识别并封禁。
处理上述每一项问题都会显著增加爬虫代码的复杂度和成本。这正是爬取 API 发挥重要作用之处,因为它们默认已处理这些问题,且成本更低。
WebScrapingAPI 便是此类服务的典范。它提供强大的功能,既能规避机器人检测机制,又能精准提取您所需的数据。
我们可以在自己的小型项目中安装 Node.js SDK,快速体验 WebScrapingAPI:
npm i webscrapingapi
现在请访问主页注册一个账户,系统将自动为您生成 API 密钥并提供免费试用。API 密钥可在仪表盘中找到,您将使用它来对发往 API 的请求进行身份验证:
就这样,您可以开始编码了!
import webScrapingApiClient from 'webscrapingapi';
const client = new webScrapingApiClient("YOUR_API_KEY");
async function exampleUsage(target_url: string) {
const api_params = {
'render_js': 1,
'proxy_type': 'datacenter',
'country': 'us',
'timeout': 60000,
'js_instructions': JSON.stringify([
{
action: "click",
selector: 'button[aria-label="Accept all"]',
timeout: 10000
}
]),
'extract_rules': JSON.stringify({
avatar: {
selector: "yt-img-shadow#avatar > img",
output: "@src",
},
name: {
selector: "yt-formatted-string#text",
output: "text",
},
handle: {
selector: "yt-formatted-string#channel-handle",
output: "text",
},
subscribers: {
selector: "yt-formatted-string#subscriber-count",
output: "text",
},
videoTitles: {
selector: "yt-formatted-string#video-title",
output: "text",
all: "1"
},
videoViews: {
selector: "div#metadata-line > span",
output: "text",
all: "1"
},
videoThumbnails: {
selector: "yt-image.ytd-thumbnail > img",
output: "@src",
all: "1"
},
videoLocations: {
selector: "a#thumbnail",
output: "@href",
all: "1"
},
})
}
const response = await client.get(target_url, api_params);
if (response.success) {
console.log(response.response.data);
} else {
console.log(response.error.response.data);
}
}
exampleUsage("https://www.youtube.com/@TechWorldwithNana/videos");
我们将之前描述的算法和 CSS 选择器转换为 API 调用。其中“js_instructions”参数将处理 Cookie 提示窗口,通过点击“接受全部”按钮。最后,“extract_rules”参数将负责数据提取。
const scroll_number = 10
let scroll_index = 0
for (let i = 0; i < scroll_number; i++) {
const js_instructions_obj = JSON.parse(api_params.js_instructions)
js_instructions_obj.push({
action: "scrollTo",
selector: `ytd-rich-grid-row.ytd-rich-grid-renderer:nth-child(${scroll_index + 3})`,
block: "end",
timeout: 1000
})
api_params.js_instructions = JSON.stringify(js_instructions_obj)
scroll_index += 3
}
在发送请求之前,请务必调整滚动逻辑。此处的处理略有不同,因为我们将指示 API 滚动至视频列表的第三行,并重复此操作 10 次。