簡體   English   中英

使用Xpath從Amazon獲取價格

[英]Getting price from Amazon with Xpath

在下一頁中:

http://www.amazon.com/Jessica-Simpson-Womens-Double-Breasted/dp/B00K65ZMCA/ref=sr_1_4_mc/185-0705108-6790969?s=apparel&ie=UTF8&qid=1413083859&sr=1-4我正在嘗試獲取價格與表達式

'//span[@id="priceblock_ourprice"]'

但結果是一個空變量。

有趣的是,在其他亞馬遜頁面中,例如: http ://www.amazon.com/SanDisk-Cruzer-Frustration-Free-Packaging--SDCZ36-032G-AFFP/dp/B007JR532M/ref=sr_1_1?s = pc&ie = UTF8&qid = 1413084653&sr = 1-1&keywords = usb

我確實有一個有效的表達方式

'//b[@class="priceLarge"]'

但是我什至不知道為什么,因為在頁面的源代碼中我找不到這樣的標簽...那為什么起作用? 以及如何獲得首頁上的價格? 謝謝!

使用PHP進行抓取時,您不能僅僅將在瀏覽器源代碼中看到的內容視為理所當然。

相反,您首先需要使用PHP獲取內容,然后查看其中的源代碼:

$url    = 'http://www.amazon.com/ ... ';
$buffer = file_get_contents($url);

然后,變量$buffer包含要抓取的HTML。

完成示例鏈接后,將顯示第一個和第二個地址都具有.priceLarge元素,其中可能包含您要查找的內容:

<span class="priceLarge">$168.00</span>
<b class="priceLarge">$14.99</b>

找出要查找的數據后,可以創建DOMDocument

$doc          = new DOMDocument();
$doc->recover = true;
$saved        = libxml_use_internal_errors(true);
$doc->loadHTML($buffer);

您可能還對解析錯誤感興趣:

/** @var array|LibXMLError[] $errors */
$errors = libxml_get_errors();
foreach ($errors as $error) {
    printf(
        "%s: (%d) [%' 3d] #%05d:%' -4d %s\n", get_class($error), $error->level, $error->code, $error->line,
        $error->column, rtrim($error->message)
    );
}
libxml_use_internal_errors($saved);

因為這是DOMDocument告訴您問題出在哪里的一種方式。 例如,重復的ID值。

將緩沖區加載到DOMDocument中之后,您可以創建DOMXPath

$xp = new DOMXPath($doc);

您將使用它從文檔中獲取實際值。

例如,這兩個示例地址HTML已顯示您正在尋找的信息是#priceBlock都包含.listprice.priceLarge

$priceBlock = $doc->getElementById('priceBlock');
printf(
    "List Price: %s\nPrice: %s\n"
    , $xp->evaluate('string(.//*[@class="listprice"])', $priceBlock)
    , $xp->evaluate('string(.//*[@class="priceLarge"])', $priceBlock)
);

這將導致以下輸出:

List Price: $48.99
Price: $14.99

如果您丟失了某些內容, $priceBlock在示例$priceBlock父節元素作為$priceBlock變量$priceBlock ,不僅允許您為Xpath使用相對路徑,而且還可以幫助您進行調試,以防丟失某些更詳細的信息:

echo $doc->saveHTML($priceBlock);

例如,這將輸出包含所有定價信息的整個<div>

如果您為自己設置了一些幫助程序類,則可以進一步使用它來從文檔中獲取其他有用的信息以進行刮擦,例如顯示價格塊內的所有標簽/類組合:

// you can find StringCollector at the end of the answer
$tagsWithClass = new StringCollector();
foreach ($xp->evaluate('.//*/@class', $priceBlock) as $class) {
    $tagsWithClass->add(sprintf("%s.%s", $class->parentNode->tagName, $class->value));
}
echo $tagsWithClass;

然后輸出收集到的字符串及其數量的列表,此處為帶有其類屬性值的標記名:

table.product (1)
td.priceBlockLabel (3)
span.listprice (1)
td.priceBlockLabelPrice (1)
b.priceLarge (1)
tr.youSavePriceRow (1)
td.price (1)

如您所見,這來自第一個示例URL,因為.pricelarge帶有<b>元素。

這是一個相對簡單的幫助程序,對於抓取您可以做更多的事情,例如以樹的形式顯示整個HTML結構。

DomTree::dump($priceBlock);

它將為您提供以下輸出,與DOMDocument::saveHTML($node)相比,它可以提供更好的使用效果:

`<div id="priceBlock" class="buying">
  +"\n\n  "
  `<table class="product">
    +<tr>
    | +<td class="priceBlockLabel">
    | | `"List Price:"
    | +"\n    "
    | +<td>
    | | `<span id="listPriceValue" class="listprice">
    | |   `"$48.99"
    | `"\n  "
    +<tr id="actualPriceRow">
    | +<td id="actualPriceLabel" class="priceBlockLabelPrice">
    | | `"Price:"
    | +"\n    "
    | +<td id="actualPriceContent">
    | | +<span id="actualPriceValue">
    | | | `<b class="priceLarge">
    | | |   `"$14.99"
    | | +"\n    "
    | | `<span id="actualPriceExtraMessaging">
    | |   +"\n        \n\n\n    "
    | |   +<span>
    | |   | `"\n        \n    "
    | |   +"\n    \n\n\n\n\n\n\n\n\n\n    \n\n\n\n\n\n \n\n\n\n\n& "
    | |   +<b>
    | |   | `"FREE Shipping"
    | |   +" on orders over $35.\n\n\n\n"
    | |   +<a href="/gp/help/customer/display.html/ref=mk_sss_dp_1/191-4381493-1931545?ie=UTF8&no...">
    | |   | `"Details"
    | |   `"\n\n\n\n\n\n\n\n\n    \n\n    \n    \n\n\n\n\n\n      \n"
    | `"\n"
    +<tr id="dealPriceRow">
    | +<td id="dealPriceLabel" class="priceBlockLabel">
    | | `"Deal Price: "
    | +"\n  "
    | +<td id="dealPriceContent">
    | | +"\n    "
    | | +<span id="dealPriceValue">
    | | +"\n    "
    | | +<span id="dealPriceExtraMessaging">
    | | `"\n  "
    | `"\n"
    +<script>
    | `[XML_CDATA_SECTION_NODE (4)]
    +<tr id="youSaveRow" class="youSavePriceRow">
    | +<td id="youSaveLabel" class="priceBlockLabel">
    | | `"You Save:"
    | +"\n    "
    | +<td id="youSaveContent" class="price">
    | | +<span id="youSaveValue">
    | | | `"$34.00\n        (69%)"
    | | `"\n    "
    | `"\n  "
    `<tr>
      +<td>
      `<td>
        `<span>
          `"o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o..."

您可以在“用PHP調試DOMDocument對象”的答案中找到它並在另一個 答案中找到它。 代碼可以在github上找到


StringCollector助手類

/**
 * Class StringCollector
 *
 * Collect strings and count them
 */
class StringCollector implements IteratorAggregate
{
    private $array;

    public function add($string)
    {
        $entry = & $this->array[$string];
        $entry++;
    }

    public function getIterator()
    {
        return new ArrayIterator($this->array);
    }

    public function __toString()
    {
        $buffer = '';
        foreach ($this as $string => $count) {
            $buffer .= sprintf("%s (%d)\n", $string, $count);
        }
        return $buffer;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM