(Редактировать: я до сих пор не нашел пути решения этой проблемы. Объект $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