【问题标题】:JSoup - Checking certain elements to see if they have text and then choosing only oneJSoup - 检查某些元素以查看它们是否有文本,然后只选择一个
【发布时间】:2018-01-24 22:54:15
【问题描述】:

我正在尝试使用 JSoup 从 Amazon 中提取价格,但我可以从两个不同的元素中提取价格。我可以从元素中的 aria-label 属性中获取它,或者我可以从元素中的文本中获取它。最好,我总是想从 aria-label 属性中获取它,但有时它不存在,所以我需要从第二个 span 类中提取它。我的问题是,如何创建一个 if 语句来检查属性以查看它是否有任何文本,如果没有,则尝试从第二个 span 类中提取文本?

另外,我试图从名称相同的类中获取多个价格,但是当我写 doc.select("span.sx-price.sx-price-large").get(0).text() 时,例如,什么都没有弹出。

这是我要从中提取项目的其中一项的 HTML 代码:

<a class="a-size-small a-link-normal a-text-normal" href="https://rads.stackoverflow.com/amzn/click/B01MZYYWUH">1</a></div>
<div class="a-row a-spacing-mini"><span class="a-size-small a-color-secondary a-text-bold">Product Description</span><br><span class="a-size-small a-color-secondary">... Cards Radeon&trade; <em>RX</em> 460 Graphics Cards Radeon&trade; R9 <em>390</em> Graphics Cards ...</span></div>
</div></div></div></div></div></div></li>
<li id="result_2" data-asin="B00IAAU6SS" class="s-result-item celwidget ">
   <div class="s-item-container">
   <div class="a-fixed-left-grid">
   <div class="a-fixed-left-grid-inner" style="padding-left:218px">
   <div class="a-fixed-left-grid-col a-col-left" style="width:218px;margin-left:-218px;_margin-left:-109px;float:left;">
      <div class="a-row">
         <div aria-hidden="true" class="a-column a-span12 a-text-center">
            <a class="a-link-normal a-text-normal" href="https://rads.stackoverflow.com/amzn/click/B00IAAU6SS"><img src="https://images-na.ssl-images-amazon.com/images/I/419c5Ci-UqL._AC_US218_.jpg" srcset="https://images-na.ssl-images-amazon.com/images/I/419c5Ci-UqL._AC_US218_.jpg 1x, https://images-na.ssl-images-amazon.com/images/I/419c5Ci-UqL._AC_US327_FMwebp_QL65_.jpg 1.5x, https://images-na.ssl-images-amazon.com/images/I/419c5Ci-UqL._AC_US436_FMwebp_QL65_.jpg 2x, https://images-na.ssl-images-amazon.com/images/I/419c5Ci-UqL._AC_US500_FMwebp_QL65_.jpg 2.2935x" width="218" height="218" alt="Product Details" class="s-access-image cfMarker" data-search-image-load></a>
            <div class="a-section a-spacing-none a-text-center"></div>
         </div>
      </div>
   </div>
   <div class="a-fixed-left-grid-col a-col-right" style="padding-left:2%;*width:97.6%;float:left;">
   <div class="a-row a-spacing-small">
      <div class="a-row a-spacing-none scx-truncate-medium sx-line-clamp-3 s-list-title-long">
         <a class="a-link-normal s-access-detail-page  s-color-twister-title-link a-text-normal" title="Arctic Accelero Xtreme IV 280(X) - High-End Graphics Card Cooler with Backside Cooler for Efficient RAM and VR-Cooling - DCACO-V930001-GBA01" href="https://rads.stackoverflow.com/amzn/click/B00IAAU6SS">
            <h2 data-attribute="Arctic Accelero Xtreme IV 280(X) - High-End Graphics Card Cooler with Backside Cooler for Efficient RAM and VR-Cooling - DCACO-V930001-GBA01" data-max-rows="3" class="a-size-medium s-inline  s-access-title  a-text-normal">Arctic Accelero Xtreme IV 280(X) - High-End Graphics Card Cooler with Backside Cooler for Efficient RAM and VR-Cooling - DCACO-V930001-GBA01</h2>
         </a>
      </div>
      <div class="a-row a-spacing-none"><span class="a-size-small a-color-secondary">by </span><span class="a-size-small a-color-secondary">ARCTIC</span></div>
   </div>
   <div class="a-row">
   <div class="a-column a-span7">
   <div class="a-row a-spacing-none"><a class="a-link-normal a-text-normal" href="https://rads.stackoverflow.com/amzn/click/B00IAAU6SS"><span aria-label="$85.99" class="a-color-base sx-zero-spacing"><span class="sx-price sx-price-large">
      <sup class="sx-price-currency">$</sup>
      <span class="sx-price-whole">85</span>
      <sup class="sx-price-fractional">99</sup>
      </span>
      </span></a><span class="a-letter-space"></span><i class="a-icon a-icon-prime a-icon-small s-align-text-bottom" aria-label="Prime"><span class="a-icon-alt">Prime</span></i>
   </div>
   <div class="a-row a-spacing-mini">
      <div class="a-row a-spacing-none"><span class="a-size-small a-color-secondary">FREE Shipping on eligible orders</span></div>
      <div class="a-row a-spacing-none"><span class="a-size-small a-color-price">Only 8 left in stock - order soon.</span></div>
   </div>
   <div class="a-row a-spacing-mini">
   <div class="a-row a-spacing-none">
      <div class="a-row a-spacing-mini"></div>
      <span class="a-size-small a-color-secondary">More Buying Choices</span>
   </div>
   <div class="a-row a-spacing-none">
   <a class="a-size-small a-link-normal a-text-normal" href="https://rads.stackoverflow.com/amzn/click/B00IAAU6SS"><span class="a-color-secondary a-text-strike"></span><span class="a-size-base a-color-base">$85.99</span>

【问题讨论】:

    标签: java html jsoup


    【解决方案1】:

    我建议选择类.sx-price 的元素,因为它的名字暗示它包含价格。然后,您可以选择需要 aria-label 属性的父元素,使用简单的正则表达式检查它是否包含价格 - 如果为真,则直接从此属性获取价格,否则从嵌套的子跨度收集数据。

    您可以在下面找到我玩过的代码,效果很好。

    final Document doc = Jsoup.parse(html);
    
    final Elements prices = doc.select(".sx-price");
    
    final Pattern pattern = Pattern.compile("^\\$?([0-9]+)\\.([0-9]{2})$");
    
    for (Element el : prices) {
        String price = "";
        if (el.parent().hasAttr("aria-label") && pattern.matcher(el.parent().attr("aria-label")).find()) {
            System.out.println("Extracting price from aria-label...");
            price = el.parent().attr("aria-label");
    
        } else {
            System.out.println("Extracting price from span body...");
            String currency = el.select(".sx-price-currency").text();
            String whole = el.select(".sx-price-whole").text();
            String fractional = el.select(".sx-price-fractional").text();
    
            price = String.format("%s%s.%s", currency, !whole.isEmpty() ? whole : "00", !fractional.isEmpty() ? fractional : "00");
        }
    
        System.out.println(price);
    }
    

    希望对你有帮助。

    【讨论】:

      【解决方案2】:

      根据您的示例 - 我们选择 span。之后检查您的“选定”元素是否为 NULL,如果它是 NOT NULL,然后从子跨度中选择文本。

      试试这个(我没有测试过 - 只是用内存写的(当然你需要先获取一个我假设你已经拥有的文档)):

      try{
       Element span = doc.select("span.a-color-base.sx-zero-spacing").first();
      
       if(span != null) {
        System.out.println(span.attr("aria-label"));
       } else {
         Element beforeSep = doc.select("span.sx-price-whole").first();
         Element afterSep = doc.select("sup.sx-price-fractional").first();
      
         System.out.println(beforeSep.text() + "." + afterSep.text());
       }
      } catch (Exception ex){
        // exception handler
      }
      

      【讨论】:

      • 那不行,因为即使上面的 HTML 代码不包含 aria-label,肯定另一个项目会有一个,所以 aria-label 永远不会为空
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      相关资源
      最近更新 更多