首页 > 解决方案 > cURL 请求耗时太长,代码有问题?

问题描述

我一直在为游戏制作会员列表并从他的分数中获取一些数据。首先,我得到一个名称列表,然后将它们插入到我的数据库中,然后将它们提供给 cURL 以从 hiscores 中获取统计信息,然后将它们更新到我的数据库中。

问题似乎是当我发出 cURL 请求时,我设法在主机显示 503 错误(可能是由于最大执行时间)之前总共更新了大约 30 个名称。但是,我必须能够更新更多。我会说100将是最低限度。

我试图优化代码,以便它运行得更快并取得一些成功。我一次查询最多可以更新 30 人。

代码本身是否有问题,为什么需要这么长时间?下面是代码的 cURL 部分,它可能不是你见过的最漂亮的。我会假设 cURL 能够一次处理更多的数据,而且我之前有类似的解决方案,而数据库没有正常工作。原因可能是https吗?以前不需要,但现在需要。

<?php
$ch = curl_init();
if(isset($_POST['submit'])){ //check if form was submitted
$conn = new mysqli($servername, $username, $password, $dbname);
    if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
    } 
            //get users
    $stmt = $conn->prepare("SELECT m.name, m.id, m.group_id, p.field_1, g.prefix, g.suffix FROM members m INNER JOIN pfields_content p ON m.id = p.id INNER JOIN groups g ON g.g_id = m.group_id WHERE
    m.group_id = 1
    ");
    $stmt->execute();
    $result = $stmt->get_result();

    while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {

    // add new member ID to database
    $conn = new mysqli($servername, $username, $password, $dbname);
    if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
    } 
    $stmt = $conn->prepare("INSERT IGNORE INTO `table` (`member_id`, `name`, `dname`) VALUES ('".$row['member_id']."', '".$row['name']."', '".$row['field_1']."')");
    $stmt->execute();

        // dname
        if($row['field_1'] != '' || $row['field_1'] != NULL) {

            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
            curl_setopt($ch, CURLOPT_URL, "https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player=".$row['field_1']);
            curl_setopt($ch, CURLOPT_HEADER, 0);

            // grab HTML
            $data = curl_exec($ch);
            $array = array();
            $array = explode(',', $data);

            //formula
            if (!empty($array[15]) && (is_numeric($array[15]))) {
                $level = ((round($array[13]/2, 0, PHP_ROUND_HALF_DOWN)+$array[9]+$array[7])/4) + (($array[3]+$array[5])*0.325);
                $level = number_format($level, 2);
                // if valid name, update
                $conn = new mysqli($servername, $username, $password, $dbname);
                if ($conn->connect_error) {
                    die("Connection failed: " . $conn->connect_error);
                } 
                $stmt = $conn->prepare("UPDATE table SET  
                member_id = '".$row['id']."',
                name = '".$row['name']."',
                cb = '".$level."' WHERE member_id = ".$row['id']."");
                $stmt->execute();
                $conn->close();
            }}}}

标签: phpmysqldatabasecurl

解决方案


Ok 看到了一些值得一提的事情:

1)为什么你只能做这么多?这是最可能的罪魁祸首:

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
        curl_setopt($ch, CURLOPT_URL, "https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player=".$row['field_1']);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        // grab HTML
        $data = curl_exec($ch);

您正在为每个站点进行外部 curl 调用,这意味着您将受制于其他站点以及解决调用需要多长时间。您可以在 curl 调用周围添加一些回声,以查看每个调用的时间。但是,遗憾的是,您可能无法从代码中获得更多速度,因为您依赖于外部进程。这可能是因为 https,或者只是他们的系统过载。就像我上面说的,如果您真的想知道每个需要多长时间,请在其周围添加一些回声,例如:

        echo "About to curl runescape " . date("H:i:s");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
        curl_setopt($ch, CURLOPT_URL, "https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player=".$row['field_1']);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        // grab HTML
        $data = curl_exec($ch);
        echo "Done with call to runescape " . date("H:i:s");

您的其余代码似乎在速度方面不是问题。但:

2)你的连接有点混乱。您打开一个连接,然后进行查询。然后一段时间开始,您打开第二个连接并进行查询。然后,如果满足正确的条件,您打开第三个连接并做一些工作,然后关闭它。最初的 2 个连接永远不会关闭,而第二个连接实际上在您的循环中被打开了多次。为什么不重复使用原来的 $conn 而不是每次都打开一个新连接?

3) 最后,如果您需要让您的 php 文件运行超过 60 秒,请在顶部添加如下内容:

set_time_limit(0);

上面应该有效地让脚本运行只要你想。不过,像上面这样的东西在 CLI 上作为 cronjob 运行比通过浏览器长时间运行的脚本更好。


推荐阅读