Оптимизация запросов к поисковым машинам

Magiys

Новичок
Оптимизация запросов к поисковым машинам

Фера Искоро!

Возник следующий вопрос:
Есть стандартый скрипт (то есть получает содержимое с помощью функции file_get_contents), который по заданному списку доменов определяет проиндексированы ли они в трех поисковых машинах.

Проблема заключается в следующем:
При списке доменов допустим в 20, отсылается 60 запросов (20 х 3), которые ужасно долго выполняются сервером, при этом можно подумать, что все зависло. Но хочется, чтобы список доменов был больше.

Предполагаемые возможные решения:
1. Как-то информировать пользователя о достигнутом прогрессе во время выполнения запросов, чтобы не создавалось впечатления о зависании.
2. Использовать мифическое свойство многопо токовости, мифическое, потому что сколько я не искал описания нигде не нашел, а только сплошные рассуждения на эту тему.

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

AndreyKl

Новичок
Доброго времени суток.
Свойство - не мифическое. Работать будет гораздо быстрее, а именно время получения 60 урлов примерно= времени получения самого долгого урла. И ещё. Можно открывать сокеты в цикле и получать через них, будет тот же эффект.

-~{}~ 31.08.06 00:45:

Вот сокеты.
Мои результаты:
Последовательно 1.0011060237885 секунд
Паралельно (сокеты) 0.57080912590027 секунд


PHP:
<html>
<HEAD>
<TITLE>Test streaming.</TITLE>
<META http-equiv="content-type" content="text/html; charset=UTF-8">
</HEAD>
<?php

$sources['google']['hostname'] = 'www.google.com';
$sources['google']['port'] = '80';
$sources['google']['get'] = '/search?hl=ru&q=php+stream';
$sources['yandex']['hostname'] = 'www.yandex.ru';
$sources['yandex']['port'] = '80';
$sources['yandex']['get'] = '/yandsearch?stype=www&nl=0&text=php+stream';
$sources['rambler']['hostname'] = 'www.rambler.ru';
$sources['rambler']['port'] = '80';
$sources['rambler']['get'] = '/srch?set=www&words=php+stream';

$time_start = microtime(1);

foreach( $sources as $key=>$host ) {
  $sources[$key]['result'] = file_get_contents('http://'.$host['hostname'].$host['get']);
}

$time_end = microtime(1);
$time = $time_end - $time_start;

echo "Последовательно $time секунд<br>\n";

$time_start = microtime(1);

foreach( $sources as $key=>$host ) {
  $sources[$key]['socket'] = fsockopen($host['hostname'], $host['port'], $errno, $errstr, 30);
  if(!$sources[$key]['socket']) {
    echo "error!";//something, what you need to do in this case...
    exit(); //if needed
  }
  $out = "GET ".$host['get']." HTTP/1.1\r\n";
  $out .= "Host: ".$host['hostname']."\r\n";
  $out .= "Connection: Close\r\n\r\n";
  fwrite($sources[$key]['socket'], $out);
}

foreach( $sources as $key=>$host ) {
  $sources[$key]['result'] = '';
  while (!feof($sources[$key]['socket'])) {
    $sources[$key]['result'] .= fgets($sources[$key]['socket'], 256);
  }
  fclose($sources[$key]['socket']);
}

$time_end = microtime(1);
$time = $time_end - $time_start;

echo "Параллельно (сокеты) $time секунд<br>\n";


?>
</html>
ЗЫ. Похоже, многопоточность действительно мифическая... в мануале не нашёл. Может тыкнет кто носом?
ЗЫЫ. Это решение ничем не хуже многопоточного, а выглядит проще (сужу по многопоточности в си и перле).

-~{}~ 31.08.06 00:47:

ЗЫЫЫ. Если сайтов больше - эффект гораздо очевиднее.

-~{}~ 31.08.06 00:49:

Да, забыл. PHP 5, в 4ке надо использовать
PHP:
$time_start = getmicrotime();

//code

$time_end = getmicrotime();
$time = $time_end - $time_start;
вместо
PHP:
$time_start = microtime(1); 

//code

$time_end = microtime(1);
$time = $time_end - $time_start;
 

AndreyKl

Новичок
WP
Спасибо, мил человек :) Век бы не нашёл, искал по слову "thread"...

-~{}~ 31.08.06 11:30:

Ещё одно, для тех, кто не очень хорошо знаком с сокетами... этот код нерабочий. В смысле, работать-то он работает, но в случае (для данного примера), если гугль не уложится в отведённые ему 30 секунд, то результатов с остальных сайтов не будет. Нужно использовать <a href="http://ru.php.net/manual/ru/function.socket-select.php">socket_select()</a> для того чтобы выбрать "готовый" сокет. Сокеты для этого нужно хранить в массиве.

-~{}~ 31.08.06 11:32:

Прошу прощения.
Нужно использовать socket_select().
 

denfdo

Новичок
Я делал подобный скрипт таким образом:
1. Человек подает заявку на сайты, скрипт заносит их в базу. В ответ получает что в скором времени результаты будут доставлены на ваш емаил.
2. Запускается крон и уже делает свое дело и рассылает результаты.
Если необходимо чтоб человек вернулся к вам на сайт, можно выслать ссылку на страницу с результатом.
 

Magiys

Новичок
AndreyKl, большое Вам спасибо за помощь, сразу заметен Ваш высокий профессионализм.

Но возникла еще одна проблема:
Загрузил коды на 3 сервера. На двух из них работают, на третьем выдает следующую ошибку:
PHP:
Warning: fsockopen(): unable to connect to "www.yandex.ru:80..."
В переменных:
$errno == 36
$errstr == Operation now in progress
Я уже пробывал искать решение этой проблемы, но нашел только то, что это как-то связано с Apache.
Но связаться с хостером сейчас не могу.

Скажите, какое есть решение этой проблемы?

P.S. Denfdo, к сожалению я не могу использовать такой приём, спасибо за отклик.

-~{}~ 31.08.06 20:14:

Нашел так же упаминание о php.ini
 

AndreyKl

Новичок
Спасибо за столь высокую оценкую Очень лестно, но я всё таки пока не тяну на уровень "высокого профессионализма", хотя стараюсь :)

работает ли на 3тьем сервере просто file("www.yandex.ru:80...");
или file_get_content('...'); ?

Вообще, мой опыт по настройке php не столь велик, но могу предположить, что если file_get_content или file работают, то php запущен в safe_mode с отключённой функцией fsocketopen(); в этом случае - либо письмо admin-у, либо переписывать код на "многопоточный", если не рабоают, то это скороее всего firewall и тут только письмо админу..

Отпишись о результатах.
 

Magiys

Новичок
Большое спасибо, AndreyKl, не надо скромничать.
Проблема оказалась банальной - Яндекс просто забанел ip сервера (когда успел на знаю?), но служба поддержки Яндекса уже решила эту проблему.
Еще раз спасибо.
 

AndreyKl

Новичок
Мда... действительно, возможна и такая причина:)
Спасибо что отписался.

-~{}~ 03.09.06 01:11:

Что такое "Фера Искоро!" ?
Google не отвечает, а словарика латинского нет под рукой...

-~{}~ 03.09.06 01:14:

Отправил приватное, простите за флуд, не подумал сразу.
 
Сверху