Intereting Posts

xpath: извлекать данные из узла с помощью xpath

Я хочу извлечь только ранг продаж (который в этом случае равен 5)

Amazon Best Sellers Ранг: № 5 в книгах (см. Top 100 в книгах)

С веб-страницы: http://www.amazon.com/Mockingjay-Hunger-Games-Book-3/dp/0439023513/ref=tmm_hrd_title_0

До сих пор я дошел до этого, который выбирает «Amazon Best Sellers Rank:»:

//li[@id='SalesRank']/b/text() 

Я использую PHP DOMDocument и DOMXPath .

Вы можете использовать чистый XPath:

 substring-before(normalize-space(/html/body//ul/li[@id="SalesRank"]/b[1]/following-sibling::text()[1])," ") 

Однако, если ваш вход немного беспорядочен, вы можете получить более надежные результаты, используя XPath для захвата текста родительского узла, а затем с помощью регулярного выражения в тексте, чтобы получить нужную вам информацию.

Демонстрация обоих методов с использованием PHP с DOMDocument и DOMXPath :

 // Method 1: XPath only $xp_salesrank = 'substring-before(normalize-space(/html/body//li[@id="SalesRank"]/b[1]/following-sibling::text()[1])," ")'; // Method 2: XPath and Regex $regex_ranktext = 'string(/html/body//li[@id="SalesRank"])'; $regex_salesrank = '/Best\s+Sellers\s+Rank:\s*(#\d+)\s+/ui'; // Test URLs $urls = array( 'http://rads.stackoverflow.com/amzn/click/0439023513', 'http://www.amazon.com/Mockingjay-Final-Hunger-Games-ebook/dp/B003XF1XOQ/ref=tmm_kin_title_0?ie=UTF8&m=AG56TWVU5XWC2', ); // Results $ranks = array(); $ranks_regex = array(); foreach ($urls as $url) { $d = new DOMDocument(); $d->loadHTMLFile($url); $xp = new DOMXPath($d); // Method 1: use pure xpath $ranks[] = $xp->evaluate($xp_salesrank); // Method 2: use xpath to get a section of text, then regex for more specific item // This method is probably more forgiving of bad HTML. $rank_regex = ''; $ranktext = $xp->evaluate($regex_ranktext); if ($ranktext) { if (preg_match($regex_salesrank, $ranktext, $matches)) { $rank_regex = $matches[1]; } } $ranks_regex[] = $rank_regex; } assert($ranks===$ranks_regex); // Both methods should be the same. var_dump($ranks); var_dump($ranks_regex); 

Выход, который я получаю:

 array(2) { [0]=> string(2) "#4" [1]=> string(2) "#3" } array(2) { [0]=> string(2) "#4" [1]=> string(2) "#3" } 

Использование :

 substring-before(substring-after($expr, '#'), ' ') 

где $expr должно быть заменено вашим выражением :

  substring-before(substring-after(//li[@id='SalesRank']/b, '#'), ' ') 

Или, если правильное выражение, которое выбирает текстовый узел, (в соответствии с @FrancisAvila):

 /html/body//ul/li[@id="SalesRank"]/b[1]/following-sibling::text()[1] 

то выше:

 substring-before( substring-after(/html/body//ul/li[@id="SalesRank"] /b[1]/following-sibling::text()[1], '#'), ' ') того, как substring-before( substring-after(/html/body//ul/li[@id="SalesRank"] /b[1]/following-sibling::text()[1], '#'), ' ')