XPath:帮助定位使用HTMLUnit抓取的DOM中的特定元素

时间:2014-04-08 14:14:30

标签: java html dom xpath htmlunit

我正在使用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");
            }
        }

1 个答案:

答案 0 :(得分:2)

我首先看到的是你如何检索<li>个节点组。只需查看您的@class属性,您就无法确定&#34; featured block twoblock boxshadow&#34;中有多少个空格,但XPath只会返回结果< em>完全等于它。 在这方面,请尝试使用更加灵活的内容,例如contains(),即//li[contains(@class, 'featured block')]

如果没有看到您定位的来源,我无法提出更多建议,但会在问题中添加答案时更新答案。

我已经在给定的代码段上尝试了你的XPath(只是/ div部分,因为那是提供的内容)并因此得到了<span class="tel" itemprop="telephone"/>。看起来像是您如何检索<li>公司节点的问题。

更新2: 根据您更新的XML代码段,您的第一个XPath //li[@class='featured block twoblock boxshadow']"看起来不会与父<li>节点匹配,具体取决于我之前提到的空格。其次,如果确实如此,则在单独的查询中检查<li>节点的属性两次,并假设您提供data-pvd-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);