Web Scrape Symfony2 – Невозможная задача – Анализ роботов

(Редактировать: я до сих пор не нашел пути решения этой проблемы. Объект $crawler кажется смешным для работы, я просто хочу проанализировать его для конкретного текста <td> , насколько это сложно? Я не могу serialize() весь объект искателя и сделать весь исходный код для веб-страницы в строку, иначе я мог бы просто проанализировать эту строку сложным способом. Пожалуйста, помогите. Я чувствую, что я описал проблему хорошо, ниже.)

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

Я могу получить страницу и получить первый бит данных, который я ищу. Первый – это URL-адрес, который печатается из javascript и лежит a тегом с onclick и является длинной строкой, поэтому я использую preg_match для просеивания и получения именно того, что мне нужно.

Следующий бит данных, который мне нужен, – это некоторый текст в <td> . Дело в том, что на этой веб-странице есть 10-20 различных тегов <table> , и нет тегов id="" или class="" поэтому их трудно изолировать. Поэтому я пытаюсь найти слова «Название события», затем перейдите к следующему тегу sibling <td> и извлеките innerHtml этого, который будет фактическим заголовком.

Проблема в том, что для второй части я не могу правильно разбираться с объектом $crawler . Я не понимаю, я сделал preg_match раньше в serialize() версии объекта $crawler , но для нижней половины я не могу правильно разобрать.

 $crawler = $client->request('GET', 'https://movies.randomjunk.com/events/EventServlet?ab=mov&eventId=154367'); $aurl = 'http://movies.randomjunk.com/r.htm?e=154367'; // event url beginning string $gas = $overview->filter('a[onclick*="' . $aurl . '"]'); $string1 = serialize($gas->filter('a')->attr('onclick')); //TEST $string1M = preg_match("/(?<=\')(.*?)(?=\')/", $string1, $finalURL); $aString = $finalURL[0]; echo "<br><br>" . $aString . "<br><br>"; // IT WORKS UP TO HERE // $title = $crawler->filterXPath('//td[. = "Event Title"]/following-sibling::td[1]')->each(funtion (Crawler $crawler, $i) { // return $node->text(); // }); // No clue why, but this doesn't work. $html = $overview->getNode(0)->ownerDocument->saveHTML(); $re = "/>Event\sTitle.*?<\\/td>.*?<td>\\K.*?(?=<\\/td>)/s"; $str = serialize($html); print_r($str); preg_match_all($re, $str, $matches); $gas2 = $matches[0]; echo "<pre>"; print_r($gas2); echo "</pre>"; на $crawler = $client->request('GET', 'https://movies.randomjunk.com/events/EventServlet?ab=mov&eventId=154367'); $aurl = 'http://movies.randomjunk.com/r.htm?e=154367'; // event url beginning string $gas = $overview->filter('a[onclick*="' . $aurl . '"]'); $string1 = serialize($gas->filter('a')->attr('onclick')); //TEST $string1M = preg_match("/(?<=\')(.*?)(?=\')/", $string1, $finalURL); $aString = $finalURL[0]; echo "<br><br>" . $aString . "<br><br>"; // IT WORKS UP TO HERE // $title = $crawler->filterXPath('//td[. = "Event Title"]/following-sibling::td[1]')->each(funtion (Crawler $crawler, $i) { // return $node->text(); // }); // No clue why, but this doesn't work. $html = $overview->getNode(0)->ownerDocument->saveHTML(); $re = "/>Event\sTitle.*?<\\/td>.*?<td>\\K.*?(?=<\\/td>)/s"; $str = serialize($html); print_r($str); preg_match_all($re, $str, $matches); $gas2 = $matches[0]; echo "<pre>"; print_r($gas2); echo "</pre>"; 

Мой preg_match просто возвращает пустой массив. Я думаю, что это проблема с поиском объекта $crawler , поскольку он состоит из многих узлов. Я пытался просто преобразовать все это в html, а затем в preg_match но он просто отказывается работать. Я сделал несколько операторов print_r , и он просто возвращает всю веб-страницу.

Вот пример некоторых из html в стороне объекта искателя:

 {lots of other html and tables} <table> <tr> <td>Title</td> <td>The Harsh Face of Mother Nature</td> <td>The Harsh Face of Mother Nature</td> </tr> . . </table> {lots of other html and tables} 

И цель состоит в том, чтобы проанализировать весь объект страницы / $crawler и получить заголовок «Суровое лицо материнской природы» .

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

Учитывая html-фрагмент выше, я смог придумать XPath:

 //table/tr/td[.='Title']/following-sibling::td[1] 

Вы можете протестировать XPath с предоставленным html-фрагментом здесь

 $html = '<table><tr><td>Event Title</td><td>The Harsh Face of Mother Nature</td><td>The Harsh Face of Mother Nature</td></tr><tr><td>Event Title</td><td>The Harsh Face of Mother Nature</td><td>The Harsh Face of Mother Nature</td></tr><tr><td>Event Title</td><td>The Harsh Face of Mother Nature</td><td>The Harsh Face of Mother Nature</td></tr></table>'; $crawler = new Symfony\Component\DomCrawler\Crawler($html); $query = "//table/tr/td[.='Event Title']/following-sibling::td[1]"; $crawler->filterXPath($query)->each(function($crawler, $i) { echo $crawler->text() . PHP_EOL; 

});

Какие результаты:

 The Harsh Face of Mother Nature The Harsh Face of Mother Nature The Harsh Face of Mother Nature 

Обновление: успешно протестировано:

 $html = '<html><table><tr><td>Event Title</td><td>The Harsh Face of Mother Nature</td><td>The Harsh Face of Mother Nature</td></tr></table><table><tr><td>Event Title</td><td>The Harsh Face of Mother Nature</td><td>The Harsh Face of Mother Nature</td></tr></table><table><tr><td>Event Title</td><td>The Harsh Face of Mother Nature</td><td>The Harsh Face of Mother Nature</td></tr></table></html>'; 

Обновление: после предоставления образца html с веб-сайта мне удалось разобраться с следующим XPath:

 //td[normalize-space(text()) = 'Event Title']/following-sibling::td[1] 

Реальная проблема была ведущим и завершающим пробелом, который был вокруг «Название события».

Хорошо, что вы можете сделать, это использовать класс в вашем:

<td class="mytitle">The Harsh Face of Mother Nature</td>

Что вы будете использовать для фильтрации вашего искателя, чтобы получить все ваши заголовки в таком массиве:

 $titles = $crawler->filter('td.mytitle')->extract(array('_text')); 

где td.mytitle – селектор css, выберите td с классом mytitle и извлеките _text, которые ссылаются на текст внутри узла.

Легко и качественно, чем регулярное выражение …

Не тестировал этот код, но он должен работать, вы можете получить дополнительную информацию и информацию об этом сканере здесь:

http://symfony.com/fr/doc/current/components/dom_crawler.html