• 最近在做一个站群项目,目前大部分网站都会限制同ip的访问频率,当然还有其他的反爬因素,这里不做考虑.
  • 正好朋友杂七杂八的有一些不同ip的服务器,于是乎可以利用起来.
  • 这样就能有多个节点来抓取数据.

完整php代码

<?php
// 关闭所有错误显示
error_reporting(0);

// 定义一个名为 CrawlWebPage 的函数,用于抓取网页内容
function CrawlWebPage($url, $headers, $timeout = 3){
    // 检查 $url 是否为空
    if('' == $url)
        return array('code'=>201,'data'=>'err');

    // 使用 cURL 初始化一个会话
    $ch = curl_init();
    // 设置要抓取的网页的 URL。
    curl_setopt($ch, CURLOPT_URL, $url);
    // 设置 HTTP 头信息。
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    // 设置是否输出 HTTP 头信息。值为 1 表示输出,0 表示不输出。
    curl_setopt($ch, CURLOPT_HEADER, 1);
    // 设置 cURL 函数执行的最长时间,单位为秒。
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    // 设置是否将抓取结果作为字符串返回。值为 1 表示返回字符串,0 表示直接输出结果。
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    // 设置连接超时时间,单位为秒。
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    // 设置是否跟随 HTTP 重定向。值为 1 表示跟随,0 表示不跟随。
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
    // 执行 cURL 会话并获取结果
    $contents = curl_exec($ch);
    // 会话的 HTTP 状态码
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $headersize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    // 获取返回的cookies
    preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', substr($contents, 0, $headersize), $matches);
    $cookies = array();
    foreach($matches[1] as $item) {
        parse_str($item, $cookie);
        $cookies = array_merge($cookies, $cookie);
    }
    // 关闭 cURL 会话
    curl_close($ch);
    // 返回结果
    return array(
        'code' =>200,
        'code_url' => $code,
        'data' => substr($contents, $headersize),
        'ck' => json_encode($cookies)
    );
}

// 检查 HTTP 请求方法是否为 POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 获取请求正文中的 JSON 数据并解码
    $json = json_decode(file_get_contents('php://input'), true);
    // 检查 JSON 数据中是否包含 data 字段
    if (isset($json['data'])) {
        // 对 data 字段进行 base64 解码并解析为数组
        $data = json_decode(base64_decode($json['data']), true);
        // 检查数组中是否包含 url 和 header 字段
        if (isset($data['url']) && isset($data['header'])) {
            // 获取 url 和 header 字段的值
            $url = $data['url'];
            $headers = array();
            foreach ($data['header'] as $key => $value) {
                $headers[] = "$key: $value";
            }
            // 调用 CrawlWebPage 函数抓取网页内容,并将结果进行 base64 编码后输出
            echo base64_encode(json_encode(CrawlWebPage($url, $headers)));
        }
    }
}

流程示意图

流程示意图

  • 这样就可以通过不同的crawl节点去并发高效率的采集数据了
  • 这里为什么会来回用base64编解码,是因为我们在发送和接受的数据中如果存在一些敏感词.就会比较尴尬,碰到一些意想不到的问题.
  • 当然如果在crawl节点跟目标站之间存在一些不可描述的内容,可能同样会被idc屏蔽的可能性.
  • 为什么代码中不处理访问失败的情况,因为某些站点可能会存在内容正常,但是给你返回一个404的状态码,所以不如直接获取到最终内容由客户端来处理更灵活.
  • 如需要更细节,代码中可以能自由更改一些功能,例如增加post数据,开关重定向,超时等.
  • 注: 运行环境php7+, 在php5.3上测试有一些问题.

简单使用示例

架设节点

目标url

组合提交的数据

  • 需要提交的json数据
{
  "url": "https://router-network.com/tools/what-is-my-user-agent",
  "header": {
    "User-Agent": "Mozilla/5u_com_cn"
  }
}
  • base64编码后的数据,data的值是上面的json数据base64编码的字符串
{"data": "eyJ1cmwiOiJodHRwczovL3JvdXRlci1uZXR3b3JrLmNvbS90b29scy93aGF0LWlzLW15LXVzZXItYWdlbnQiLCJoZWFkZXIiOnsiVXNlci1BZ2VudCI6Ik1vemlsbGEvNXVfY29tX2NuIn19"}

用postman访问测试


  • 提交数据返回了一个base64编码字符串
    postman提交测试

  • 可以使用 base64 进行解码后
    base64解码

  • 可以使用 json工具 格式化,可以看到之前提交的 "User-Agent": "Mozilla/5u_com_cn"
    json格式化


可以看到 data 字段中则是返回的源代码, ck 字段中则是返回的cookies
大功告成!

最后修改:2023 年 09 月 23 日
如果觉得我的文章对你有用,请随意赞赏