Я хочу извлечь только ранг продаж (который в этом случае равен 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], '#'), ' ')