巧用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();
        }
    }
}

以上代码比较简单,笔者为了提高接口的返回速度做了以下优化:

  1. 拦截各种无关资源的加载
  2. 打开网页等待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追踪平台吧。