Код для поиска строк в исходном коде по многим URL

#php #curl #web-scraping #explode #strstr

#php #curl #очистка веб-страниц #взорваться #strstr

Вопрос:

Я хочу ввести очень длинный список URL-адресов и выполнить поиск определенных строк в исходном коде, выводя список URL-адресов, содержащих строку. Звучит достаточно просто, не так ли? Я разработал приведенный ниже код, входным сигналом которого является html-форма. Вы можете попробовать это на pelican-cement.com/findfrog .

Кажется, что это работает в половине случаев, но сбивается несколькими URL-адресами в разных порядках. При поиске ‘adsense’ он правильно идентифицирует politics1.com из

 cnn.com
politics1.com
  

однако, если перевернуть вывод, он будет пустым. Как я могу получить надежные, непротиворечивые результаты? предпочтительно что-то, во что я мог бы ввести тысячи URL-адресов?

 <html>
<body>

<?
set_time_limit (0);

$urls=explode("n", $_POST['url']);

$allurls=count($urls);

for ( $counter = 0; $counter <= $allurls; $counter  ) {

 $ch = curl_init();
 curl_setopt($ch, CURLOPT_URL,$urls[$counter]);
 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_CUSTOMREQUEST,'GET');
 curl_setopt ($ch, CURLOPT_HEADER, 1); 
 curl_exec ($ch); 
 $curl_scraped_page=curl_exec($ch); 

$haystack=strtolower($curl_scraped_page);
$needle=$_POST['proxy'];
if (strlen(strstr($haystack,$needle))>0) {

echo $urls[$counter];
echo "<br/>";
curl_close($ch);
}
}




//$FileNameSQL = "/googleresearch" .  abs(rand(0,1000000000000000))  .  ".csv";
//$query = "SELECT * FROM happyturtle INTO OUTFILE '$FileNameSQL' FIELDS TERMINATED BY ','";
//$result = mysql_query($query) or die(mysql_error());

//exit;

echo '$FileNameSQL';





?>

</body>
</html>
  

Ответ №1:

Немного реорганизовал ваш код. Основным виновником были пробелы. Вам нужно обрезать строку URL перед ее использованием (т.Е. trim($url); ).

Другие изменения:

  • Установите поисковый запрос вне цикла for, поскольку он никогда не меняется.
  • Настройте объект curl вне цикла и повторно используйте его, просто изменяя URL каждый раз.
  • Используйте curl_setopt_array(), чтобы задать несколько параметров curl в одном операторе.
  • Используйте цикл foreach, поскольку вы все равно выполняете итерацию по всему массиву, и код становится чище.
  • Использование stripos() более эффективно, чем strstr(), и в любом случае не чувствительно к регистру.
  • Используйте компаратор !==, чтобы предотвратить подразумеваемое приведение к типу (FALSE !== 0, но FALSE == 0).
  • Проверьте возвращаемую строку $ html, поскольку curl_exec() может вернуть FALSE в случае сбоя.
  • Закройте объект curl в конце (т. Е. также за пределами оператора if).

Приведенный ниже код можно запустить на моем быстром макете.

 <html>
<body>

<form action="search.php" method="post"> 
  URLs: <br/>
  <textarea rows="20" cols="50" input type="text" name="url" /></textarea><br/>

  Search Term: <br/>
  <textarea rows="20" cols="50" input type="text" name="proxy" /></textarea><br/>

  <input type="submit" /> 
</form>

<?
  if(isset($_POST['url'])) {
    set_time_limit (0);

    $urls = explode("n", $_POST['url']);
    $term = $_POST['proxy'];
    $options = array( CURLOPT_FOLLOWLOCATION => 1,
                      CURLOPT_RETURNTRANSFER => 1,
                      CURLOPT_CUSTOMREQUEST  => 'GET',
                      CURLOPT_HEADER         => 1,
                      );
    $ch = curl_init();
    curl_setopt_array($ch, $options);

    foreach ($urls as $url) {
      curl_setopt($ch, CURLOPT_URL, trim($url));
      $html = curl_exec($ch);

      if ($html !== FALSE amp;amp; stristr($html, $term) !== FALSE) { // Found!
        echo $url;
      }
    }

    curl_close($ch);
  }
?>

</body>
</html>
  

Комментарии:

1. Спасибо! Проблема сейчас в том, что время ожидания истекает всякий раз, когда вводится более 50 URL-адресов. @Джеймс Ан

2. Обертывание кода в пакетном процессе на PHP намного сложнее. Вместо немедленной обработки отправки формы вам нужно будет записать поисковый запрос и все URL-адреса в файл или базу данных. Затем вызовите другой PHP-файл, который будет обрабатывать вплоть до истечения времени ожидания, сохраняя результаты в файле или базе данных, и верните HTML-файл, который покажет ход выполнения и автоматически (обновит) вызовет пакетный PHP-файл снова, пока не будут обработаны все URL-адреса.

Ответ №2:

Возможно, вам следует вызвать

 curl_close($ch);
  

Независимо от того, находит ли он строку на очищенной странице или нет. Помимо этого я не вижу ничего явно неправильного в коде.

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

Ответ №3:

Пара настроек, не уверен, помогут ли они, но все же

 $url_to_go = trim($urls[$counter]);
if($url_to_go){
 $ch = curl_init();
 curl_setopt($ch, CURLOPT_URL,$url_to_go);
 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_CUSTOMREQUEST,'GET');
 curl_setopt ($ch, CURLOPT_HEADER, 1); 
 $curl_scraped_page=curl_exec($ch); 
 curl_close($ch);

 // more code follows
}
  

Ответ №4:

Может ли это быть возврат каретки / пробел вокруг URL-адресов, который отключает его? Возможно, стоило бы поместить в

 $urls[$counter] = trim($urls[$counter]);
  

в начале вашего цикла for.

Также:

 if (strpos($haystack, $needle) !== false) {
    [...]
}
  

это более эффективный способ проверки, содержит ли одна строка другую. Вы также могли бы использовать stripos здесь вместо strtolower(), сначала обработав все это (не уверен, улучшит ли это ситуацию).