Я написал небольшой скрипт, который извлекает информацию с веб-сайта с использованием PHP DOMXPath
учебный класс.
Я запрашиваю <div class="sku" />
и выполнить substring-before
на результат. Результат содержит текст, неразрывные пробелы, разрыв строки и другой текст.
Итак, что я пытаюсь сделать, это сократить до \r\n
, Он отлично работает, когда я использую следующий запрос:
$query = "substring-before(//div[@class='sku'],'\xC2\xA0\xC2\xA0\r\n')";
но терпит неудачу, как только я изменяю кавычки (которые не должны иметь никакого значения):
$query = 'substring-before(//div[@class="sku"],"\xC2\xA0\xC2\xA0\r\n")';
или же
$query = 'substring-before(//div[@class=\'sku\'],\'\xC2\xA0\xC2\xA0\r\n\')';
Как это возможно и как я могу преодолеть это?
Живой пример здесь: http://codepad.viper-7.com/R1rCaj
Стиль цитат имеет значение, потому что когда строка заключена в двойные кавычки, PHP будет интерпретировать больше escape-последовательностей для специальных символов — включая то, что вы используете для неразрывного пространства \xC2\xA0
, возврат каретки \r
и перевод строки \n
,
Когда они заключены в одинарные кавычки '\xC2\xA0\r\n'
Как и во втором запросе, PHP обрабатывает их как буквальные символы — обратную косую черту, x, C, 2 … и т. д.
Небольшая дополнительная подсветка синтаксиса может помочь показать это, escape-последовательности оранжевого цвета:
Если в вашей строке уже есть то, что должно быть escape-последовательностями в виде буквенных символов, и есть ни за что чтобы исправить это*, Вы в какой-то грязной ситуации, когда заменяете их сами.
это preg_replace_callback()
позаботится о последовательности в вашем примере, и тривиально распространиться на остальные escape-последовательности, поддерживаемые двойными кавычками:
// Known good.
$query1 = "substring-before(//div[@class='sku'],'\xC2\xA0\xC2\xA0\r\n')";
// Known bad.
$query2 = 'substring-before(//div[@class=\'sku\'],\'\xC2\xA0\xC2\xA0\r\n\')';
$query2 = preg_replace_callback(
'/\\\\(?:[rn]|(?:x[0-9A-Fa-f]{1,2}))/',
function ($matches) {
switch (substr($matches[0], 0, 2)) {
case '\r':
return "\r";
case '\n':
return "\n";
case '\x':
return hex2bin(substr($matches[0], 2));
}
},
$query2
);
var_dump($query1 === $query2); // Now equal?
Выход:
bool(true)
(* Действительно, вы должны исправить это у источника.)
Вы можете сделать это легко с simple_html_dom
для скачивания: http://sourceforge.net/projects/simplehtmldom/files/
Руководство : http://simplehtmldom.sourceforge.net/manual.htm
<?php
// include simple html dom library
include('./lib/simple_html_dom.php');
$url="http://www.vosteen-shop.de/p-261232-edelstahl-herz-acero-zum-hngen-lnge-10cm-breite-10cm-silber-glanz.aspx";
// get html in $html var
$html=file_get_html($url);
// find your class div.sku (plaintext) or you can get (innertext)
$results=$html->find('div.sku',0)->innertext;
$explode=explode("<b",$results);
$results=trim($explode[0]);
echo $results ;
?>