选择Nokogiri中的变体

时间:2017-10-29 02:39:55

标签: html css ruby nokogiri

我正在抓这两个网站:

  1. https://www.library.uq.edu.au/uqlsm/availablepcsembed.php?branch=Law
  2. https://www.library.uq.edu.au/uqlsm/availablepcsembed.php?branch=BSL
  3. 不幸的是,他们有变化。一个在href标签内有级别名称(例如,级别2),而另一个只是纯文本。如何根据哪一个选择其中一个?

    我试过这个无济于事:

    level.css(/"a[href]"|".left"/).text
    

    以下是2个HTML部分的缩短版本:

    <table class="chart"> 
        <tr valign="middle">
            <td class="left">Level 2</td> <!-- the problem -->
            <td class="middle"><div style="width:86%;"><strong>86%</strong></div></td>
        </tr>
    </table>
    

    <table class="chart">
        <tr valign="middle">
            <td class="left"><a href="availablepcsembed.php?branch=BSL&room=Lvl1">Level 1</a></td>
            <td class="middle"><div style="width:32%;"><strong>32%</strong></div></td>
        </tr>
    </table>
    

    我的代码(从代码部分编辑为整个方法)

    def self.scrape_details_page(library_url)
        details_page = Nokogiri::HTML(open(library_url))
    
        details_page.css("table.chart tr").collect do |level|
            right = level.css(".right").text.split
            {level: level.css("a[href]").text, available: right[0], out_of_available: right[3]}
        end
    end
    

3 个答案:

答案 0 :(得分:2)

如果你想要做的是抓住最里面的div中的文本,你应该能够通过在解析的#text元素上调用td来完全潜入。无需考虑和行走可能存在于其中的额外标签,例如链接标记。鉴于你的代码是:

details_page.css("table.chart tr").collect do |level|
     level = level.text
end

对于每个元素,将水平标签或百分比值(内部文本)拉为字符串,并将值分配给levels变量。

编辑:另外,如果你关心的只是获得关卡标签,你可以直接按类过滤元素:

details_page.css("table.chart tr td.left").collect do |level|
     level = level.text
end

答案 1 :(得分:1)

answer by jk_应该适用于这种特殊情况。

在更一般的情况下,如果您要使用CSS选择器,则需要为&#34;或&#34;使用CSS语法。 (逗号)因此,如果您打算使用您最初询问的选择器,那么它就是

level.css('a[href], .left').text

答案 2 :(得分:0)

感谢@jk_的灵感,我使用.css(".left").text修复了它。这只会选择td内的左侧tr中的所有文字。

工作代码:

def self.scrape_details_page(library_url)
    details_page = Nokogiri::HTML(open(library_url))

    details_page.css("table.chart tr").collect do |level|
        right = level.css(".right").text.split
        {level: level.css(".left").text, available: right[0], out_of_available: right[3]}
    end
end