Как я могу контролировать порядок получения данных при получении ответа на несколько скручиваний в php? - PullRequest
0 голосов
/ 07 ноября 2018

В моем сценарии мне может потребоваться сделать более 100 запросов curl для получения необходимой информации. Нет никакой возможности получить эту информацию заранее, и у меня нет доступа к серверу, на который я буду отправлять запросы. Мой план - использовать curl_multi_init () . Каждый ответ придет в формате JSON. Проблема в том, что мне нужно получать информацию в том порядке, в котором я ее разместил, иначе я не буду знать, куда все идет после того, как ответ придет. Как мне решить эту проблему.

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Когда вы получите дескрипторы от curl_multi_info_read, вы можете сравнить эти дескрипторы со своим списком ключей, а затем, конечно, использовать клавишу, чтобы узнать, куда направляется ваш ответ. Вот прямая реализация, основанная на модели, которую я использую для скребка:

// here's our list of URL, in the order we care about
$easy_handles['google']     = curl_init('https://google.com/');
$easy_handles['bing']       = curl_init('https://bing.com/');
$easy_handles['duckduckgo'] = curl_init('https://duckduckgo.com/');

// our responses will be here, keyed same as URL list
$responses = [];

// here's the code to do the multi-request -- it's all boilerplate
$common_options = [ CURLOPT_FOLLOWLOCATION => true, CURLOPT_RETURNTRANSFER => true ];
$multi_handle = curl_multi_init();
foreach ($easy_handles as $easy_handle) {
    curl_setopt_array($easy_handle, $common_options);
    curl_multi_add_handle($multi_handle, $easy_handle);
}
do {
    $status = curl_multi_exec($multi_handle, $runCnt);
    assert(CURLM_OK === $status);
    do {
        $status = curl_multi_select($multi_handle, 2/*seconds timeout*/);
        if (-1 === $status) usleep(10); // reported bug in PHP
    } while (0 === $status);
    while (false !== ($info = curl_multi_info_read($multi_handle))) {
        foreach ($easy_handles as $key => $easy_handle) { // find the response handle
            if ($info['handle'] === $easy_handle) {       // from our list
                if (CURLE_OK === $info['result']) {
                    $responses[$key] = curl_multi_getcontent($info['handle']);
                } else {
                    $responses[$key] = new \RuntimeException(
                        curl_strerror($info['result'])
                    );
                }
            }
        }
    }
} while (0 < $runCnt);

Большая часть этого является стандартным механизмом для многократной выборки. Строки, нацеленные на ваш конкретный вопрос:

foreach ($easy_handles as $key => $easy_handle) { // find the response handle
    if ($info['handle'] === $easy_handle) {       // from our list
        if (CURLE_OK === $info['result']) {
            $responses[$key] = curl_multi_getcontent($info['handle']);

Зациклите свой список, сравнивая возвращенный дескриптор с каждым сохраненным дескриптором, а затем используйте соответствующий ключ для заполнения вашего ответа.

0 голосов
/ 07 ноября 2018

Очевидно, что поскольку запросы являются асинхронными, вы не можете предсказать порядок, в котором будут поступать ответы. Поэтому в вашем проекте вы должны предусмотреть, чтобы каждый запрос включал «некоторый случайный бит информации» - так называемый nonce - который каждый клиент каким-то образом будет обязан дословно возвращать вам.

Исходя из этого "одноразового номера", вы сможете затем соединить каждый ответ с запросом, который его инициировал, и отбросить любые случайные биты мусора, которые блуждают "на ровном месте".

В противном случае, не существует (!) решения вашей проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...