Я пытаюсь отказаться от некоторого контента с веб-сайта, но приведенный ниже код не работает (не показывая никакого вывода). вот код
$url="some url"; $otherHeaders=""; //here i am using some other headers like content-type,userAgent,etc some curl to get the webpage ... .. curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); $content=curl_exec($ch);curl_close($ch); $page=new DOMDocument(); $xpath=new DOMXPath($page); $content=getXHTML($content); //this is a tidy function to convert bad html to xhtml $page->loadHTML($content); // its okay till here when i echo $page->saveHTML the page is displayed $path1="//body/table[4]/tbody/tr[3]/td[4]"; $path2="//body/table[4]/tbody/tr[1]/td[4]"; $item1=$xpath->query($path1); $item2=$xpath->query($path2); echo $item1->length; //this shows zero echo $item2->length; //this shows zero foreach($item1 as $t) echo $t->nodeValue; //doesnt show anything foreach($item2 as $p) echo $p->nodeValue; //doesnt show anything
Я уверен, что что-то не так с вышеуказанным кодом xpath
. xpaths
верны. Я проверил вышеуказанные xpaths
с FirePath (a firefox addon)
. Я знаю, что мне не хватает чего-то очень глупого здесь, но я не могу разобраться. Пожалуйста помоги. Я проверил аналогичный код для соскабливания ссылок из Wikipedia
(определенно, xpaths
разные), и он работает хорошо. Поэтому я не понимаю, почему приведенный выше код не работает для других URLs
. Я очищаю содержимое HTML
с помощью Tidy
поэтому я не вижу проблемы с xpath, не связанным с HTML-кодом? Я проверил длину nodelist
после $item1=$xpath->query($path1)
который равен 0
что означает, что что-то не так с $xpath->query
потому что xpaths
верны, поскольку я проверил с FirePath
я изменил мой код немного, как указано, и использовал loadXML
вместо loadHTML
. но это дает мне ошибку, поскольку Entity 'nbsp' not defined in Entity
поэтому я использовал параметр LIBXML_NOENT
для замены сущностей, но все же ошибки остаются.
Да, вам не хватает чего-то очень простого: это XHTML, поэтому вы должны зарегистрировать (и использовать!) Правильное пространство имен, прежде чем сможете ожидать результатов.
$xpath->registerNamespace('x', 'http://www.w3.org/1999/xhtml'); $path1="//x:body/x:table[4]/x:tbody/x:tr[3]/x:td[4]"; $path2="//x:body/x:table[4]/x:tbody/x:tr[1]/x:td[4]"; $item1=$xpath->query($path1); $item2=$xpath->query($path2);
Похоже, что проблема каким-то образом связана с XPath и пространствами имен. Руководство Php показало интересный комментарий пользователя
Если вы зарегистрировали свои пространства имен, загрузили свой XHTML и т. Д. В свой объект DOMDocument XPath и все еще не можете заставить его работать, убедитесь, что вы не использовали функцию loadHTML () или loadHTMLFile () DOMDocument. Для XHTML всегда используйте версии XML , иначе ваш XPath никогда не будет работать.
В вашем коде используется loadHTML()
$content=getXHTML($content); //this is a tidy function to convert bad html to xhtml $page->loadHTML($content); // its okay till here when i echo $page->saveHTML the page is displayed
HTML не является пространством имен, поэтому loadHTML()
может не устанавливать пространства имен в элементах документа, даже если исходный документ (или XHTML, полученный Tidy) имел их.
Поскольку вы используете Tidy для преобразования документа в XHTML, я предполагаю, что вы можете безопасно использовать loadXML()
без использования ошибок синтаксического анализа. Обратите внимание, что это потребует ввода корректно сформированного XML. Также он может не знать о предопределенных объектах HTML, таких как
и если это так, он не может заменить сущности своими правильными значениями символов. Если возникает такая проблема, попробуйте установить различные параметры для loadXML()
.
Я слышал, что FireFox добавляет элемент tbody
если таковой нет .
В дополнение к или независимо от совета @ Tomalak, попробуйте выражения XPath с удаленным шагом местоположения /tbody
.
Кроме того, используйте другой инструмент в качестве XPizer Visualizer для создания правильных выражений XPath и сразу увидите, что они выбирают.
Этот вопрос напоминает мне, что много раз решение проблемы заключается в простоте, а не в осложнениях. я пытался использовать namespaces
, error corrections
и т. д., но решение просто потребовало тщательной проверки кода. проблема с моим кодом была в порядке loadHTML()
и xpath initialization
. первоначально заказ был
$xpath=new DOMXPath($page); $page->loadHTML($content);
сделав это, я фактически инициализировал xapth
на пустой документ. теперь меняя порядок, сначала загружая dom
с помощью html
а затем инициализируя xpath
я смог получить желаемые результаты. Также, как предполагалось, удалив элемент xpath
из xpath
поскольку firefox
автоматически вставляет его. поэтому правильный xpath
должен быть
$path1="//body/table[4]/tr[3]/td[4]"; $path2="//body/table[4]/tr[1]/td[4]";
спасибо всем за их предложения и с этим.
(Попробуйте следующее в сочетании с другими ответами и отдельно от других ответов, поскольку это другие возможные оговорки.)
Если ваш XPath не работает, попробуйте применить только его части, чтобы убедиться, что вы действительно следуете правильному пути. Так что сделайте что-нибудь вроде:
$path1="//body"; $item1 = $xpath->query($path1); foreach ($item1 as $t) { // to see the full XML of the returned node, as the nodeValue may be empty echo $t->ownerDocument->saveXML($t); }
Затем продолжайте увеличивать XPath до требуемого местоположения.
Кроме того, если вы обнаружите, что nodeValue и textContent ваших узлов пуст, вы должны убедиться, что вы загружаете DOMDocument с правильным кодированием (например, если ответ cURL возвращает UTF-8, вам нужно передать «UTF- 8 'в качестве второго параметра при построении DOMDOcument).