【问题标题】:XPath: Help in locating a specific element in a DOM scraped using HTMLUnitXPath:帮助定位使用 HTMLUnit 抓取的 DOM 中的特定元素
【发布时间】:2014-04-09 04:06:06
【问题描述】:

我正在使用 HTMLUnit 抓取网页,并从网页中收集了 DOM 节点列表。

在这些“公司”DOM 节点中的每一个都是我想要抓取的一些数据。例如,我想要此节点内的电话号码文本:

现在,该元素将是 div 元素的子元素,而 div 元素又是公司节点内另一个 div 元素的子元素。访问它的正确 XPath 行是什么?这是我最新的尝试,没有返回任何结果。

 List<DomNode> companies = (List<DomNode>) page.getByXPath("//li[@class='featured block twoblock    boxshadow']");
        for (int j = 0; j < companies.size(); j++) {

            DomNode company = companies.get(j);

                // retrieve telephone number
                DomNode telephone = (DomNode) company.getByXPath(
                        "//li[@data-pvd-p='"+j+1+"']/div[@class='listingWrapper']/div[@class='itemInfo']/span[@class='tel']").get(0);

}

这是一个 HTML 示例,内容:

        <li class="featured block twoblock boxshadow" data-pvd-p="3" data-pvd-c="0046176330000011028" data-pvd-et="sv" data-pvd-l="true">

    <div class="listingWrapper" itemtype="http://schema.org/LocalBusiness" itemscope="">
        <a href="/Craddock-Electrical-Services-Ltd/0046176330000011028/"></a>
        <div class="itemInfo">
            <div class="tradeImage" itemprop="member" itemscope="" itemtype="http://schema.org/Organization"></div>
            <h2>
                <a itemprop="name" href="/Craddock-Electrical-Services-Ltd/0046176330000011028/"></a>
            </h2>
            <span class="tel" itemprop="telephone"></span>
            <div class="listLinks"></div>
            <div id="addressBar"></div>
        </div>
        <div class="itemInfo2"></div>
        <div class="clearLeft"></div>
        <ul class="features"></ul>
        <div class="clearLeft"></div>
        <p class="promo" itemprop="description"></p>
    </div>
</li>

更新 2:

这是我的 XPath 代码的当前状态。

List<DomNode> companies = (List<DomNode>) page
                .getByXPath("//li[contains(@class, 'featured block')]");
        for (int j = 0; j < companies.size(); j++) {

            String url = "";
            DomNode company = companies.get(j);
            DomElement web = null;

            // retrieve name
            DomNode name = (DomNode) company.getByXPath("//a[@itemprop='name']").get(j);

            if (companiesLogged.contains(name.getTextContent().trim()) != true) {
                companiesLogged.add(name.getTextContent().trim());

                // retrieve telephone number
                DomNode telephone = (DomNode) company.getByXPath("div[@class='listingWrapper']/div[@class='itemInfo']/span[@class='tel']").get(0);


                // retrieve website
                try{
                web = (DomElement) company.getByXPath("div[@class='listingWrapper']/div[@class='itemInfo']" +
                        "/div[@class='listLinks']/a[@id='linkWebsite']").get(0);
                } catch(IndexOutOfBoundsException e){
                    System.out.print(" (No Website) ");
                }

                try{
                url = web.getAttribute("href");
                } catch (IndexOutOfBoundsException e){
                    url = "N/A";
                }

                System.out.println(name.getTextContent().trim() + "   "
                        + telephone.getTextContent().trim()
                 +"   "+url.trim());

            } else {
                System.out.println("Company already logged");
            }
        }

【问题讨论】:

  • 请发布您要定位的 XML/XHTML 或其中的 sn-p,以便我们提出更好的建议

标签: java html dom xpath htmlunit


【解决方案1】:

我看到的第一件事是您如何检索&lt;li&gt; 节点组。仅查看您的@class 属性,您无法真正判断“featured block twoblock boxshadow”中有多少个空格,但 XPath 只会在 完全等于它时返回结果。 在这方面,请尝试使用更灵活的东西,例如contains(),即//li[contains(@class, 'featured block')]

在没有看到您的目标来源的情况下,我无法提供更多建议,但会在将答案添加到问题时更新答案。

我已经在给定的 sn-p 上尝试了您的 XPath(只是 /div 部分,因为这是提供的),结果返回 &lt;span class="tel" itemprop="telephone"/&gt;。您检索 &lt;li&gt; 公司节点的方式似乎存在问题。

更新 2: 根据我之前提到的空格,从您更新的 XML sn-p 中,您的第一个 XPath //li[@class='featured block twoblock boxshadow']" 看起来不会与父节点 &lt;li&gt; 匹配。其次,如果确实如此,您将在单独的查询中两次检查&lt;li&gt; 节点的属性,并假设您提供data-pvd-p 值的索引(在sn-p 中从3 开始)将始终与列表索引匹配(从 0 开始,加上你的 +1)。我建议删除这部分//li[@data-pvd-p='"+j+1+"'] 并以//div 开头。

所以是这样的:

List<DomNode> companies = (List<DomNode>) page.getByXPath("//li[contains(@class, 'featured block']");
        for (DomNode node : companies) {

                // retrieve telephone number
                DomNode telephone = (DomNode) node.getByXPath(
                        "div[@class='listingWrapper']/div[@class='itemInfo']/span[@class='tel']").get(0);

【讨论】:

  • 谢谢,我已经更新以显示 HTML。我还将使用您对
  • 节点的建议。
  • @GreenGodot 您从 /div 开始的 XPath 似乎没问题,如果您想发布带有封装
  • 的完整 sn-p,我也可以尝试一下。
  • 嗨,很抱歉,我以为我第一次包含它。
  • Np,它有助于发布尽可能多的与问题开始相关的信息。更新了答案
  • 道歉,但只是顺便说一句。并非所有像我原​​来的问题中那样的 sn-ps 都必须有电话号码。因此,当我存储号码时,它可能与错误的公司相关联。在我做任何其他事情之前,有没有办法检查该元素是否作为原始
  • 标签的子元素存在?
  • 猜你喜欢
    相关资源
    最近更新 更多
    热门标签