Получить частичную веб-страницу

Есть ли способ ограничения количества данных, которые CURL будет получать? Я собираю данные со страницы размером 50 КБ, однако данные, которые мне нужны, находятся в верхней четверти страницы, поэтому мне действительно нужно извлечь только первые 10 КБ страницы.

Я спрашиваю, потому что мне нужно следить за большим количеством данных, что приводит к тому, что я передаю около 60 ГБ данных в месяц, когда релевантно только около 5 ГБ этой полосы пропускания.

Я использую PHP для обработки данных, однако я гибок в подходе к извлечению данных, я могу использовать CURL, WGET, fopen и т. Д.

Один подход, который я рассматриваю,

$fp = fopen("http://www.website.com","r");
fseek($fp,5000);
$data_to_parse = fread($fp,6000);

Означает ли вышесказанное, что я перевезу только 6 КБ с www.website.com или открою загрузку www.website.com в память, означая, что я все равно перенесу полные 50 КБ?

4 ответа

Решение

Вы также можете выполнить то, что ищете, используя CURL.

Если вы посмотрите документацию для CURLOPT_WRITEFUNCTION, вы можете зарегистрировать обратный вызов, который вызывается всякий раз, когда данные доступны для чтения из CURL. Затем вы можете сосчитать полученные байты, а когда вы получили более 6000 байтов, вы можете вернуть 0, чтобы прервать оставшуюся часть передачи.

Документация libcurl описывает обратный вызов немного подробнее:

Эта функция вызывается libcurl, как только получаются данные, которые необходимо сохранить. Возвратите количество байтов, фактически обработанных. Если эта сумма отличается от суммы, переданной вашей функции, она сообщит об ошибке библиотеке и прервет передачу и возвратит CURLE_WRITE_ERROR.

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

На самом деле это больше HTTP, чем вопрос CURL.

Как вы уже догадались, вся страница будет загружена, если вы используете fopen. Неважно, если вы ищете смещение 5000 или нет.

Лучший способ добиться желаемого - использовать частичный HTTP-запрос GET, как указано в HTML RFC ( http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html):

Семантика метода GET меняется на "частичное GET", если сообщение запроса включает в себя поле заголовка Range. Частичное GET запрашивает, чтобы была передана только часть объекта, как описано в разделе 14.35. Метод частичного GET предназначен для уменьшения ненужного использования сети, позволяя завершить частично извлеченные объекты без передачи данных, уже сохраненных клиентом.

Подробности частичных запросов GET с использованием диапазонов описаны здесь: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

Попробуйте запрос HTTP RANGE:

GET /largefile.html HTTP/1.1
Range: bytes=0-6000

если сервер поддерживает запросы диапазона, он вернет код ответа 206 Partial Content с заголовком Content-Range и запрошенным диапазоном байтов (если нет, он вернет 200 и весь файл). см. http://benramsey.com/archives/206-partial-content-and-range-requests/ для хорошего объяснения запросов диапазона.

см. также Возобновляемая загрузка при использовании PHP для отправки файла?,

Это загрузит всю страницу с fopen позвоните, но тогда он будет читать только 6 КБ с этой страницы.

Из руководства по PHP:

Чтение прекращается, как только выполняется одно из следующих условий:

  • длина байтов была прочитана
Другие вопросы по тегам