не в состоянии очистить контент с сайта - PullRequest
6 голосов
/ 29 мая 2011

Я пытаюсь удалить некоторый контент с веб-сайта, но приведенный ниже код не работает (не отображается никакого вывода). вот код

$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 LIBXML_NOENT для замены сущностей, но все равно ошибки остаются.

Ответы [ 5 ]

5 голосов
/ 29 мая 2011

Да, вам не хватает чего-то очень простого: это 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);
4 голосов
/ 31 мая 2011

Кажется, что проблема как-то связана с XPath и пространствами имен.В руководстве по PHP появился интересный пользовательский комментарий

Если вы зарегистрировали свои пространства имен, загрузили XHTML и т. Д. В объект XPath DOMDocument и все еще не могу заставить его работать, убедитесь, что вы не использовали функцию 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().

2 голосов
/ 29 мая 2011

Я слышал, что FireFox добавляет элемент tbody, если его нет .

В дополнение или независимо от совета @ Tomalak, попробуйте выражения XPath с удаленным шагом /tbody.

Также используйте другой инструмент как Визуализатор XPath , чтобы создать правильные выражения XPath и сразу увидеть, что они выбирают.

1 голос
/ 10 июня 2011

Этот вопрос напоминает мне, что решение проблемы часто заключается в простоте, а не в сложностях.я пытался namespaces, error corrections и т. д., но решение просто требовало тщательной проверки кода.проблема с моим кодом была порядка loadHTML() и xpath initialization.изначально заказ был

$xpath=new DOMXPath($page);
$page->loadHTML($content);

, делая это, я фактически инициализировал xapth в пустом документе.теперь изменим порядок, сначала загрузив dom с html, а затем инициализировав xpath, и я смог получить желаемые результаты.Также предполагается, что при удалении элемента tbody из xpath as firefox автоматически вставляет его.поэтому правильный xpath должен быть

$path1="//body/table[4]/tr[3]/td[4]";
$path2="//body/table[4]/tr[1]/td[4]";

, спасибо всем за их предложения и за это.

0 голосов
/ 30 мая 2011

(Попробуйте следующее как в сочетании с другими ответами, так и отдельно от них, поскольку они являются другими возможными предостережениями.)

Если ваш 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).

...