Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 无法访问块内的Nokogiri元素_Ruby_Nokogiri - Fatal编程技术网

Ruby 无法访问块内的Nokogiri元素

Ruby 无法访问块内的Nokogiri元素,ruby,nokogiri,Ruby,Nokogiri,我成功运行了以下程序: require 'nokogiri' require 'open-uri' own = Nokogiri::HTML(open('https://www.sec.gov/cgi-bin/own-disp?action=getowner&CIK=0001513362')) own_table = own.css('table#transaction-report') p own_table.css('tr').css('td')[4].css('a').attr

我成功运行了以下程序:

require 'nokogiri'
require 'open-uri'

own = Nokogiri::HTML(open('https://www.sec.gov/cgi-bin/own-disp?action=getowner&CIK=0001513362'))
own_table = own.css('table#transaction-report')

p own_table.css('tr').css('td')[4].css('a').attr('href').value
=>“/Archives/edgar/data/0001513362/000162828016019444/0001628280-16-019444-index.htm”

但是,当我尝试在块中使用上面的元素时(如下面的代码所示),我得到了nil:NilClass的NoMethodError

我感到困惑,因为我认为块中的局部变量链接与上面代码中的对象相同

此外,如果我将下面链接的定义更改为:

link=row.css('td')[4]。类

我得到了一个没有错误的散列,表示link的值是Nokogiri::XML::Element

有人能解释一下,为什么我有一个Nokogiri::XML::Element对象,但不能在其上运行css方法。特别是当我可以在第一段代码中运行它时

require 'nokogiri'
require 'open-uri'

own = Nokogiri::HTML(open('https://www.sec.gov/cgi-bin/own-disp?action=getowner&CIK=0001513362'))
own_table = own.css('table#transaction-report')


own_table.css('tr').each do |row|
  names = [:acq, :transaction_date, :execution_date, :issuer, :form, :transaction_type, :direct_or_indirect_ownership, :number_of_securities_transacted, :number_of_securities_owned, :line_number, :issuer_cik, :security_name, :url]
  values = row.css('td').map(&:text)
  link = row.css('td')[4].css('a').attr('href').value
  values << link
  hash = Hash[names.zip values]
  puts hash
end

secown.rb:11:in `block in <main>': undefined method `css' for nil:NilClass (NoMethodError)
    from /Users/piperwarrior/.rvm/gems/ruby-2.2.1/gems/nokogiri-1.6.7.2/lib/nokogiri/xml/node_set.rb:187:in `block in each'
    from /Users/piperwarrior/.rvm/gems/ruby-2.2.1/gems/nokogiri-1.6.7.2/lib/nokogiri/xml/node_set.rb:186:in `upto'
    from /Users/piperwarrior/.rvm/gems/ruby-2.2.1/gems/nokogiri-1.6.7.2/lib/nokogiri/xml/node_set.rb:186:in `each'
    from secown.rb:8:in `<main>'
需要“nokogiri”
需要“打开uri”
own=Nokogiri::HTML(打开)https://www.sec.gov/cgi-bin/own-disp?action=getowner&CIK=0001513362'))
own#table=own.css('表#事务报告')
own_table.css('tr')。每行|
名称=[:acq,:交易日期,:执行日期,:发行人,:表格,:交易类型,:直接或间接所有权,:交易证券数量,:持有证券数量,:行号,:发行人cik,:证券名称,:url]
values=row.css('td').map(&:text)
link=row.css('td')[4].css('a').attr('href').value

值关键的洞察是,在第一种情况下,
own_table.css('tr')
返回一个
NodeSet
.css('td')
找到该NodeSet中任何节点的所有
td
,然后找到第四个节点(作为程序员来说,第五个是普通人:p)

第二个代码段将每一行单独视为一个
节点
,然后查找所有后代
td
,然后选择第四个

因此,如果你有这种结构:

tr id=1
  td id=2
  td id=3
tr id=4
  td id=5
  td id=6
  td id=7
  td id=8
  td id=9
然后第一个代码片段将为您提供ID7TD(它是所有tr中的第四个td);第二个代码段将尝试在ID1TR中查找第四个
td
,然后在ID4TR中查找第四个
td
,但它会出错,因为ID1TR没有第四个td


编辑:具体地说,检查完URL后,第一个
tr
没有
td
;其他的都有12个。所以
own_table.css('tr')[0].css('td')[4]。class
NilClass
,而不是您报告的
Nokogiri::XML::Element

关键的洞察是,在第一种情况下,
own_table.css('tr')
返回一个
节点集
.css('td'))
查找该节点集中任何节点的后代的所有
td
,然后查找第四个节点(作为程序员,第五个是普通人:P)

第二个代码段将每一行单独视为一个
节点
,然后查找所有后代
td
,然后选择第四个

因此,如果你有这种结构:

tr id=1
  td id=2
  td id=3
tr id=4
  td id=5
  td id=6
  td id=7
  td id=8
  td id=9
然后第一个代码片段将为您提供ID7TD(它是所有tr中的第四个td);第二个代码段将尝试在ID1TR中查找第四个
td
,然后在ID4TR中查找第四个
td
,但它会出错,因为ID1TR没有第四个td

编辑:具体地说,检查完URL后,第一个
tr
没有
td
;其他的都有12个。所以
own_table.css('tr')[0].css('td')[4].class
NilClass
,而不是您报告的
Nokogiri::XML::Element

考虑以下几点:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<html>
  <body>
    <div><span><p>foo</p></span></div>
    <div id="bar"><span><p>bar</p></span></div>
  </body>
</html>
EOT
css
,如
search
xpath
返回一个节点集,
text
将连接所有返回节点的文本,使得从单个节点检索文本变得困难。而是使用:

doc.css('bar p').map(&:text)
它将返回一个数组,其中包含找到的每个节点的文本:

doc.css('div p').text
# => "foobar"
与:

doc.css('div p').map(&:text)
# => ["foo", "bar"]
另请参见“”。

考虑一下:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<html>
  <body>
    <div><span><p>foo</p></span></div>
    <div id="bar"><span><p>bar</p></span></div>
  </body>
</html>
EOT
css
,如
search
xpath
返回一个节点集,
text
将连接所有返回节点的文本,使得从单个节点检索文本变得困难。而是使用:

doc.css('bar p').map(&:text)
它将返回一个数组,其中包含找到的每个节点的文本:

doc.css('div p').text
# => "foobar"
与:

doc.css('div p').map(&:text)
# => ["foo", "bar"]

另请参见“”。

我的意思是将block中的局部变量link更改为link=row.css('td')[4]。类给出Nokogiri::XML::element我知道您的意思。它适用于80行(具有12个
td
的行);不适用于第一行(没有
td
)。@Amadan是对的,第一行有一个
th
,而不是
td
,这是因为你得到了
NoMethodError
values=row.css('td')。map(&:text)=>[]
@Amadan我通过使用带有索引的每个_忽略了第一行,只在索引时迭代!=0这就行了。我的意思是将block中的局部变量link改为link=row.css('td')[4]。类给出了Nokogiri::XML::element我知道你们的意思。它适用于80行(具有12个
td
的行);不适用于第一行(没有
td
)。@Amadan是对的,第一行有一个
th
,而不是
td
,这是因为你得到了
NoMethodError
values=row.css('td')。map(&:text)=>[]
@Amadan我通过使用带有索引的每个_忽略了第一行,只在索引时迭代!=0成功了,请读“成功”。当询问代码问题时,我们需要最少的输入数据(本例中为HTML)来说明问题本身。不要要求我们去一个网站浏览整个页面,因为这会减慢我们对您的响应时间,并影响我们帮助他人的能力。您不需要使用
css
search
链接每个标记。而是使用更复杂的选择器,从一个地标跳到另一个地标,再跳到标记中的目标。这就不那么脆弱了。此外,在选择答案之前,您应该等待更长的时间。请阅读“”。当询问代码问题时,我们需要最少的输入数据(本例中为HTML)来说明问题本身。不要要求我们去一个网站,并通过阅读
doc.css('div p').map(&:text)
# => ["foo", "bar"]