有没有办法解析在 ruby 的标签中包含 javascript 的 html?

Is there a way to parse html that include javascript in tags in ruby?

我正在 Ruby 解决网络抓取问题。我已经看到多个与此相关的问题和答案,但在 none 中我看到 HTML 其中包含一些 JavaScript 框架,但我不知道如何去做。我只想 select HTML 和 return 对象数组。以下是我的脚本和 HTML 代码。 name、currency、balance等值的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>

使用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 可以在 class 的定义中链接参数,但通常可以使用更通用的 class 选择器;这仅取决于 HTML.

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

at_css 几乎等同于 at,而 Nokogiri 在 99.9% 的情况下足够聪明来确定选择器是 CSS 还是 XPath,所以我倾向于使用 at因为我手指比较懒