巧用Vercel Serverless 获取IPData Business数据
背景
ipdata.co 提供了专业的API可以用来查询IP的相关情况,其中Business套餐包含了代理检测、IP打分数据,但收费对个人用户相对较贵。笔者研究出了一种简单的方法可以直接免费获取其Business数据,记录在这里分享给大家。声明,本文所述内容仅可用于交流和学习,请勿用于任何商业行为,有能力的朋友还是建议购买正版服务!
实现原理
IPData.co的官网提供了直接输入IP查询的功能,其返回的原始数据包含了Business套餐中所有的功能。我们可以通过模拟网页打开的方式直接调用。这样做的好处是避免了去逆向其前端代码,完美绕过前端的各种校验。弊端在于是模拟浏览器访问,访问速度与付费接口相差较大,笔者经过优化后接口返回时间依然在1.5s左右,对时间有严格要求的朋友还是考虑直接付费吧。
实现步骤
Vercel是近年来比较流行的一个网站托管平台,它不仅可以部署静态网站,还提供了Serverless API,提供了支持多种语言的Runtime。笔者很多API服务都跑在这个平台上,免费的额度也足够使用。
要想模拟浏览器打开网页,不得不提到Puppeteer/Playwright了。相信论坛里面很多弄爬虫的小伙伴都用过这个工具。Puppeteer 是一个 Node 库,它提供了高级的 API 并通过 DevTools 协议来控制 Chrome(或Chromium)。通俗来说就是一个 Headless Chrome 浏览器 (也可以配置成有 UI 的,默认是没有的)。
由于Vercel的 Serverless API 是基于AWS Lambda, 单个函数文件大小有50Mb的限制,如果直接使用最新的Puppeteer就会超过限制,所以我们可以直接别人封装好的库chrome-aws-lambda。
说了那么多还是直接上代码吧,代码比较简单,核心如下:
import chromium from 'chrome-aws-lambda';
export default async function handler(req, res) {
let browser = null;
const { ip } = req.query;
if (!ip) {
return res.status(200).json({ code: -1, msg: 'ip blank' });
}
// 这里可以再对IP的合法性做进一步校验
try {
browser = await chromium.puppeteer.launch({
headless: true,
args: chromium.args,
defaultViewport: chromium.defaultViewport,
executablePath: await chromium.executablePath,
headless: chromium.headless,
ignoreHTTPSErrors: true,
});
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', (req) => {
const blocked = ["image", "stylesheet", "media", "font"];
if (blocked.includes(req.resourceType())) {
req.abort();
return;
}
req.continue();
});
await page.goto("https://ipdata.co", { waitUntil: 'domcontentloaded' });
const data = await page.evaluate((ipaddr) => {
return new Promise(reslove => {
// 这里的api-key似乎是不变的
$.get("https://api.ipdata.co/" + ipaddr + '?api-key=eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9', resp => {
reslove(resp);
}, "jsonp")
});
}, ip);
res.status(200).json(data)
} catch (error) {
return res.status(200).json({ code: -1, msg: `${error}` });
} finally {
if (browser) {
await browser.close();
}
}
}
以上代码比较简单,笔者为了提高接口的返回速度做了以下优化:
- 拦截各种无关资源的加载
- 打开网页等待
domcontentloaded时间触发,而非默认的page load completely
结果
➜ ~ time curl https://xxxxxxx.vercel.app/api/ip\?ip\=1.8.8.8
{"ip":"1.8.8.8","is_eu":false,"city":null,"region":null,"region_code":null,"region_type":null,"country_name":"China","country_code":"CN","continent_name":"Asia","continent_code":"AS","latitude":34.77320098876953,"longitude":113.72200012207031,"postal":null,"calling_code":"86","flag":"https://ipdata.co/flags/cn.png","emoji_flag":"🇨🇳","emoji_unicode":"U+1F1E8 U+1F1F3","asn":{"asn":"AS38345","name":"Internet Domain Name System Beijing Engineering Resrarch Center Ltd.","domain":null,"route":"1.8.8.0/24","type":"business"},"company":{"name":"Internet Domain Name System Beijing Engineering Resrarch Center Ltd.","domain":null,"network":"1.8.8.0/24","type":"business"},"languages":[{"name":"Chinese","native":"中文","code":"zh"}],"currency":{"name":"Chinese Yuan","code":"CNY","symbol":"CN¥","native":"CN¥","plural":"Chinese yuan"},"time_zone":{"name":null,"abbr":null,"offset":null,"is_dst":null,"current_time":null},"threat":{"is_tor":false,"is_vpn":false,"is_icloud_relay":false,"is_proxy":false,"is_datacenter":false,"is_anonymous":false,"is_known_attacker":false,"is_known_abuser":false,"is_threat":false,"is_bogon":false,"blocklists":[],"scores":{"vpn_score":86,"proxy_score":96,"threat_score":84,"trust_score":12}}}
curl https://xxxxxxx.vercel.app/api/ip\?ip\=1.8.8.8 0.01s user 0.00s system 0% cpu 1.523 total
经过多次测试,接口返回时间在1.5s上下,对接口响应速度要求不高的场景完全适用。此外,还可以对查询结果放入Redis做缓存,相信可以进一步提高速度。
总结
现在的互联网基础架构真的是太强大了,各种免费的资源都可以直接使用,对开发人员极其友好。笔者业务上的许多服务都是利用这些资源直接构建的,省时又省心,关键还免费。等有时间笔者再分享下如何用Vercel Serverless + Google Tag Manager + GA 构建支持Google、FB、Tiktok、Taboola等通用的Pixel追踪平台吧。