我正在开发一个白帽网络爬虫,它会定期登录我的账户,并使用Ruby和Watir和Nokogiri为我检查一些信息。
以下是我试图从中提取信息的简化HTML:
<div class="navbar navbar-default navbar-fixed-top hidden-lg hidden-md" style="z-index: 1002">
<div class="banner-g">
<div class="container">
<div id="user-info">
<div id="acct-value">
<a href="https://www.testsite.org/Profile/MyShares" title="Change in value of your shares">GAIN/LOSS <span class="SPShares">-$12.85</span></a>
</div>
<div id="committed">
<a href="https://www.testsite.org/Profile/MyShares" title="Amount paid for your shares">INVESTED <span class="SPPortfolio">$152.11</span></a>
</div>
<div id="avail">
<a href="https://www.testsite.org/Profile/MyShares">AVAILABLE <span class="SPBalance">$26.98</span></a>
</div>
我正在尝试提取摘录底部的$26.98.。
下面是我正在使用的三个代码片段。除了XPath,它们几乎都是一样的。前两个函数完美地返回值,但第三个函数总是返回值"0“,即使它”应该“返回"$26.98”或"26.98“。
val_one = page_html.xpath(".//*[@id='openone']/div/div[2]/div[1]/div/div[2]/table/tbody/tr[2]/td[1]").text.gsub(/\D/,'').to_i
val_two = page_html.xpath(".//*[@id='opentwo']/div/div[2]/div[2]/div/div[2]/table/tbody/tr[2]/td[1]").text.gsub(/\D/,'').to_i
val_three = page_html.xpath(".//*[@id='avail']/a/span").text.gsub(/\D/,'').to_i
puts val_three我假设这是XPath的问题,但我已经在这里检查了几十个XPath故障排除问题,但没有一个有效。我用FirePath和"XPath Checker“检查了XPath。我也尝试过让XPath搜索"SPBalance“类,但得到了相同的结果。
当我从结尾处删除to.i时,它返回一个空行而不是零。
在站点的其他地方使用Watir时,我可以通过调用.focus来修复记录值的问题,但是对于这段代码,使用.focus会导致错误消息:
undefined method `focus' for []:Nokogiri::XML::NodeSet (NoMethodError)我想.focus不能为诺基亚工作。
更新:将HTML替换为更干净/更完整的版本。
我继续尝试访问该数据单元格的不同方法,包括xpath、css和一种搜索方法。有人告诉我xpath在这个页面上不能工作,所以我花了更多的时间尝试让css工作。另一个人告诉我,这个页面有Javascript,这会阻止Watir工作。因此,我尝试为Selenium重写应用程序。Selenium没有解决这个问题,还造成了一大堆其他问题。
更新:听从Tin的建议后,我发现当使用curl下载节点时,该节点在HTML中实际上是不可见的。
我现在正在尝试使用Watir而不是Nokogiri (他建议的)来访问节点。以下是我到目前为止尝试过的一些方法:
avail_funds = browser.span :class => 'SPBalance'
avail_funds.exists?
avail_funds.text
avail_funds = browser.span(:css, 'span[customattribute]').text
avail_funds = browser.div(:id => "avail").a(:href => "/Profile/MyShares").span(:class => "SPBalance").text
avail_funds = browser.span(:xpath, ".//*[@id='avail']/a/span").text
avail_funds = browser.span(:css, 'span[class="SPBalance"]').text
avail_funds = browser.span.text
avail_funds = browser.div.text
browser.span(:class, "SPBalance").focus
avail_funds = browser.span(:class, "SPBalance").text
avail_funds = @browser.span(:class => 'SPBalance').inner_html
puts @browser.spans(:class => "SPBalance")
puts @browser.span(:class => "SPBalance")
texts = @browser.spans(:class => "SPBalance").map do |span|
span.text
end到目前为止,以上所有代码都返回空行或错误消息。
在通过curl下载的HTML中可以看到ID为"user-info“的div类。然而,它下面的一切都是看不见的。
当我尝试的时候:
avail_funds = browser.div(:id => "user-info").text我只能看到空行。
当我尝试的时候:
avail_funds = browser.div(:class => "navbar navbar-default navbar-fixed-top hidden-xs hidden-sm").text我得到了实际的文本!但不幸的是,字符串没有包含我想要的值。
我也试过了:
puts browser.html因为我认为,如果该值在该版本的HTML中可见,就像通过我的Firefox插件一样,我可以向下解析到我想要的值。但不幸的是,该值在该版本的HTML中不可见。
发布于 2016-03-21 09:18:53
通过前两个命令,您可以直接从表格单元格中提取数据,从文档的根开始,在最后一个命令中,您从中心开始。
尝试给出span id并再次获取数据,然后增加复杂性,您将在xpath中发现错误。
发布于 2016-03-22 04:13:32
第一个问题是你正在尝试使用一个很长很长的选择器,它引用了不存在的标签:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<head>
<body class="cbp-spmenu-push">
<div id="FreshWidget" class="freshwidget-container responsive" data-html2canvas-ignore="true" style="display: none;">
<div id="freshwidget-button" class="freshwidget-button fd-btn-right" data-html2canvas-ignore="true" style="display: none; top: 235px;">
<link rel="stylesheet" href="/Content/css/NavPushComponent.css"/>
<script src="/Scripts/classie.js"/>
<script src="/Scripts/modernizr.custom.js"/>
<div class="navbar navbar-default navbar-fixed-top hidden-lg hidden-md" style="z-index: 1002">
<div class="banner-g">
<div class="container">
<div id="user-info">
<div id="acct-value">
<div id="committed">
<div id="avail">
<a href="/Profile/MyBalance">
AVAILABLE
<span class="SPBalance">$31.59</span>
EOT
doc.at('tbody') # => nil".//*@id='openone'/div/div2/div1/div/div2/table/tbody/tr2/td1“".//*@id='opentwo'/div/div2/div2/div/div2/table/tbody/tr2/td1”
在您的示例中没有<tbody>标记,并且在自然创建的HTML中很少有标记,特别是在人们手动创建它的情况下。我们通常在HTML语言中看到有人从浏览器的“查看源代码”显示中抓取<tbody>,这是在他们的引擎破坏了HTML语言以使其可读之后的结果输出。不要使用该输出。相反,始终直接转到源代码,使用wget或curl下载页面并使用编辑器检查它,甚至在命令行上使用nokogiri some_url并在那里查看它。
第二个问题是您的HTML代码片段无效,因为它充满了未终止的标记。Nokogiri将在错误的HTML上进行修复,这实际上会移动节点,使查找节点变得困难,特别是在调试时。在这种特殊情况下,Nokogiri能够终止它们,但遵守标记闭包很重要。
下面是我要用到的:
value = doc.at('span.SPBalance').text # => "$31.59"这是使用CSS,它通常比XPath更具可读性。at的意思是“查找第一个匹配项”,等同于search('span.SPBalance').first。
XPath的等价物是:
doc.at('//span[@class="SPBalance"]')
doc.at('//span[@class="SPBalance"]').text # => "$31.59"一旦我有了值,就很容易对其进行操作。
value[/[\d.]+/].to_f # => 31.59继续..。
第三次总是返回值"0“,即使它应该返回"$31.59”或"31.59“
'$31.58'.to_i # => 0
'$'.to_i # => 0
'31.58'.to_i # => 31
'$31.58'.to_f # => 0.0
'31.58'.to_f # => 31.58to_f和to_i的文档分别说:
返回将字符串中的前导字符解释为浮点数的结果。
和
返回将str中的前导字符解释为基数整数(介于2和36之间)的结果。
在这两种情况下,“主角”都很重要。
使用.focus的
会导致以下错误消息:
未定义的方法‘`focus’for []:Nokogiri::XML::NodeSet (NoMethodError)
我想.focus不能为诺基亚工作。
您可以随时检查the NodeSet documentation,这将确认focus不是一种方法。
https://stackoverflow.com/questions/36119782
复制相似问题