是否有一种方法可以解析在ruby标签中包含javascript的html?

问题描述 投票:1回答:1

我正在研究Ruby中的网络抓取问题。我已经看到了与此相关的多个问题和答案,但是没有一个人看到HTML中包含一些JavaScript框架,而且我不知道该怎么做。我只想选择HTML并返回一个对象数组。以下是我的脚本和HTML代码。诸如名称,货币,余额之类的值的HTML类是相似的,该如何解决呢?

content = document.css("div.acc-list").map do |parameters| 
    name = parameters.at_css("p.s3.bold.row.acDesc").text.strip, # argument?
    currency = parameters.at_css(".row.ccy").text.strip, # argument?
    balance = parameters.at_css(".row.acyOpeningBal").text.strip # argument?
    Account.new name, currency, balance
end
pp content

这些HTML段落位于其他多个类中,我认为这归因于该框架。但是,它们在<div class = acc-list div>...</div>内,当我将“ div.acc-list”分配给“ content”变量时,我认为我做得正确。

<!-- HTML for name -->

<td bindonce="" ng-repeat="col in gridOptions.columns" sg-bind-html-compile="col.cellTemplate" bo-class="col.className" bo-style="{width: col.remWidth }" 
class="ng-scope icon-two-line-col" style="width: 17.3333rem;">
  <div style="width: 17.333333333333332rem" class="first-cell cellText ng-scope">
    <i bo-class="{'active':row.selected }" class="i-32 active icon i-circle-account"></i>
    <div class="info-wrapper" style="">
      <p class="s3 bold" bo-bind="row.acDesc">Name_value</p>   # value
      <a ui-sref="app.layout.ACCOUNTS.DETAILS.{ID}({id:'091601003439274'})" href="/Bank/accounts/details/BG37FINV91503006938102">
        <span bo-bind="row.iban">BG37FINV91503006938102</span>
        <i class="i-arrow-right-5x8"></i>
      </a>
    </div>
  </div>
</td>


<!-- HTML for currency -->

<td bindonce="" ng-repeat="col in gridOptions.columns" sg-bind-html-compile="col.cellTemplate" bo-class="col.className" bo-style="{width: col.remWidth }" 
class="ng-scope" style="width: 4.4rem;">
    <div style="width: 4.4rem" class="text-center cellText ng-scope">
        <span bo-bind="row.ccy">EUR</span>   # value
    </div>
</td>


<!-- HTML for balance -->

<td bindonce="" ng-repeat="col in gridOptions.columns" sg-bind-html-compile="col.cellTemplate" bo-class="col.className" bo-style="{width: col.remWidth }" 
class="ng-scope" style="width: 8.73333rem;">
    <div style="width: 8.733333333333333rem" class="text-right cellText ng-scope">
        <span bo-bind="row.acyAvlBal | sgCurrency">1 523.08</span>   # value
    </div>
</td>
html ruby nokogiri
1个回答
1
投票

使用CSS:

require 'nokogiri'

document = Nokogiri::HTML(<<EOT)
<div class="acc-list">
  <!-- HTML for name -->
  <td>
    <div class="first-cell cellText ng-scope">
      <div class="info-wrapper">
        <!-- # value -->
        <p class="s3 bold">Name_value</p> 
      </div>
    </div>
  </td>


  <!-- HTML for currency -->
  <td>
    <div class="text-center cellText ng-scope">
      <!-- # value -->
      <span>EUR</span> 
    </div>
  </td>

  <!-- HTML for balance -->
  <td>
    <div class="text-right cellText ng-scope">
      <!-- # value -->
      <span>1 523.08</span> 
    </div>
  </td>
</div>
EOT

现在已加载DOM:

content = document.css('div.acc-list').map do |div| 
    name = div.at("p.s3.bold").text.strip # => "Name_value"
    currency = div.at("div.text-center > span").text.strip  # => "EUR"
    balance = div.at("div.text-right > span").text.strip # => "1 523.08"
  [ name, currency, balance ]
end
# => [["Name_value", "EUR", "1 523.08"]]

您的HTML示例中有很多无关的信息,这些信息遮盖了该特定森林中的树木。我删除了它,因为它没有用。 (并且,在提交问题时,您应该在简化非必需信息的过程中自动执行此操作,以便我们都可以专注于实际问题。)

CSS不关心节点名称classid以外的参数。如果需要那种细粒度的访问,class可以在类的定义中链接参数,但是通常可以使用更通用的类选择器;它仅取决于HTML。

大多数XML和HTML解析基本上是相同的策略:找到一个外部占位符,在其中查找并迭代获取所需的信息。我不能完全证明这一点,因为您的示例仅具有外部div,但是您可能可以想像到处理内部循环的必要代码。

[at_css几乎等同于at,并且Nokogiri在99.9%的时间内足够聪明地确定选择器是CSS还是XPath,因此我倾向于使用at,因为我的手指很懒。

© www.soinside.com 2019 - 2024. All rights reserved.