2011-09-29 5 views
1

이 코드는 완전히 손상되었습니다.Variable에 값을 할당 할 수 없습니다 : 정의되지 않은 메소드`[] 'for nil : NilClass (NoMethodError)

나는 다음과 같은 코드가 있습니다

puts block.at_xpath("*/img")["width"].to_i 

을하지만

width = block.at_xpath("*/img")["width"].to_i 

로 변경할 때이 오류 얻을 : 내가 거기에 박았을 때

NokogiriTUT.rb:70:in `blockProcessor': undefined method `[]' for nil:NilClass (NoMethodError) 

그것을 기대 값을 반환합니다.

업데이트 : 여기

 def blockProcessor(block) 
    header = block.xpath('td[@class="default"]/*/span[@class="comhead"]') 
    array = header.text.split 
    if array[0] != nil #checks to make sure we aren't at the top of the parent list 
     ### Date and Time ### 
     if array[2] == 'hours' || array[2] == 'minutes' 
      date = Time.now 
     else 
      days = (array[1].to_i * 24 * 60 * 60) 
      date = Time.now - days 
     end 

     ##Get Comment## 
     comment = block.at_xpath('*/span[@class="comment"]') 

     hash = comment.text.hash 
     #puts hash 

     ##Manage Parent Here## 

      width = block.at_xpath("*/img")["width"].to_i 



      prevlevel = @parent_array[@parent_array.length-1][1] 
      if width == 0 #has parents 
       parentURL = header.xpath('a[@href][3]').to_s 
       parentURL = parentURL[17..23] 
       parentURL = "http://news.ycombinator.com/item?id=#{parentURL}" 
       parentdoc = Nokogiri::HTML(open(parentURL)) 
       a = parentdoc.at_xpath("//html/body/center/table/tr[3]/td/table/tr") 
       nodeparent = blockProcessor(a) 
       @parent_array = [] 
       node = [hash, width, nodeparent] #id, level, parent 
       @parent_array.push node  
      elsif width > prevlevel 
       nodeparent = @parent_array[@parent_array.length-1][0] 
       node = [hash, width, nodeparent] 
       @parent_array.push node 
      elsif width == prevlevel 
       nodeparent = @parent_array[@parent_array.length-1][2] 
       node = [hash, width, nodeparent] 
       @parent_array.push node 
      elsif width < prevlevel 
       until prevlevel == w do 
        @parent_array.pop 
        prevlevel = @parent_array[@parent_array.length-1][1] 
       end 
       nodeparent = @parent_array[@parent_array.length-1][2] 
       node = [hash, width, nodeparent] 
       @parent_array.push node 
      end 
     puts "Author: #{array[0]} with hash #{hash} with parent: #{nodeparent}" 

     ##Handles Any Parents of Existing Comments ## 
     return hash 
    end 
end 
    end 

는에 역할을하는 블록이다.

<tr> 
    <td><img src="http://ycombinator.com/images/s.gif" height="1" width="0"></td> 
    <td valign="top"><center> 
    <a id="up_3004849" href="vote?for=3004849&amp;dir=up&amp;whence=%2f%78%3f%66%6e%69%64%3d%34%6b%56%68%71%6f%52%4d%38%44"><img src="http://ycombinator.com/images/grayarrow.gif" border="0" vspace="3" hspace="2"></a><span id="down_3004849"></span> 
    </center></td> 
    <td class="default"> 
    <div style="margin-top:2px; margin-bottom:-10px; "><span class="comhead"><a href="user?id=patio11">patio11</a> 12 days ago | <a href="item?id=3004849">link</a> | <a href="item?id=3004793">parent</a> | on: <a href="item?id=3004471">Ask HN: What % of your job interviewees pass FizzB...</a></span></div> 
    <br><span class="comment"><font color="#000000">Every time FizzBuzz problems come up among engineers, people race to solve them and post their answers, then compete to see who can write increasingly more nifty answers for a question which does not seek niftiness at all.<p>I'm all for intellectual gamesmanship, but these are our professional equivalent of a doctor being asked to identify the difference between blood and water. You can do it. <i>We know</i>. Demonstrating that you can do it is not the point of the exercise. We do it to have a cheap-to-administer test to exclude people-who-cannot-actually-program-despite-previous-job-titles from the expensive portions of the hiring process.</p></font></span><p><font size="1"><u><a href="reply?id=3004849&amp;whence=%2f%78%3f%66%6e%69%64%3d%34%6b%56%68%71%6f%52%4d%38%44">reply</a></u></font></p> 
    </td> 
</tr> 
+0

at_xpath를 호출하기 전에'puts 블록 '을 추가하려고 했습니까? 어쩌면 당신은'block'을 바꾸는 부작용이있을 수도 있습니다. – knut

+0

@knut, 나는 그저 두번 확인했는데 그 것이 작동합니다. 또한 puts가 내가 기대하고 바라는 가치를 제공한다는 것은 이상한 일입니다. 내가 원하는 것은 그것을 변수에 할당하는 것뿐입니다. –

+0

'width = ...'과제의 문맥은 무엇이고 '공장'은 무엇입니까? –

답변

3

기본 문제는 XPath를 이해하지 못한다는 것입니다. (당신은 좋은 회사에 있으며 XPath는 매우 혼란 스럽습니다.) 선택자는 자신이 생각하는 것과 일치하지 않습니다. 특히, 하나

*/img 

그런

//img 

또는 뭔가를해야 불면 그.

이제 때문에 XPath는 선택기,

block.at_xpath("*/img") 

가 nil 일이 루비 문장의 값을 아무것도 일치하지 않습니다. 그리고 nil은 []을 지원하지 않으므로 ["width"]을 호출 할 때 Ruby는 undefined method [] for nil:NilClass 오류로 불평합니다.

왜 변수를 할당 할 때만 불어납니다 ... 예, 실제로 어떤 일이 일어나고있는 건 아닙니다. 당신은 아마도 다른 것을 너무 바꿨을 것입니다.


그리고 지금, 내가 다른 희망 건설적인 코드 비판을 할 수 있도록하십시오

  • 귀하의 질문은 분명히 어려운 답변을 할 수 있도록 설계되었습니다. 앞으로 문제의 코드를 분리하고 숙제를 전부 붙이기 만하면됩니다 (또는이 스크레이퍼가 무엇이든간에).

  • 당신은 우리가 우리의 컴퓨터에 그대로 실행할 수있는 하나의 실행 가능한 루비 파일, 예컨대 :

으로 그것을 만든 경우 추가 좋은 것입니다.

require "nokogiri" 
doc = Nokogiri.parse <<-HTML 
<tr> 
    <td><img src="http://ycombinator.com/images/s.gif" height="1" width="0"></td> 
    <td valign="top"><center> 
    <a id="up_3004849" href="vote?for=3004849&amp;dir=up&amp;whence=%2f%78%3f%66%6e%69%64%3d%34%6b%56%68%71%6f%52%4d%38%44"><img src="http://ycombinator.com/images/grayarrow.gif" border="0" vspace="3" hspace="2"></a><span id="down_3004849"></span> 
    </center></td> 
    <td class="default"> 
    <div style="margin-top:2px; margin-bottom:-10px; "> 
     <span class="comhead"> 
     <a href="user?id=patio11">patio11</a> 12 days ago | <a href="item?id=3004849">link</a> | <a href="item?id=3004793">parent</a> | on: <a href="item?id=3004471">Ask HN: What % of your job interviewees pass FizzB...</a> 
     </span> 
    </div> 
    <br><span class="comment"><font color="#000000">Every time FizzBuzz problems come up among engineers, people race to solve them and post their answers, then compete to see who can write increasingly more nifty answers for a question which does not seek niftiness at all.<p>I'm all for intellectual gamesmanship, but these are our professional equivalent of a doctor being asked to identify the difference between blood and water. You can do it. <i>We know</i>. Demonstrating that you can do it is not the point of the exercise. We do it to have a cheap-to-administer test to exclude people-who-cannot-actually-program-despite-previous-job-titles from the expensive portions of the hiring process.</p></font></span><p><font size="1"><u><a href="reply?id=3004849&amp;whence=%2f%78%3f%66%6e%69%64%3d%34%6b%56%68%71%6f%52%4d%38%44">reply</a></u></font></p> 
    </td> 
</tr> 
HTML 

width = doc.at_xpath("*/img")["width"].to_i 

그런 식으로 우리는 컴퓨터로 디버깅 할 수 있습니다.

  • 은 이제 루비를 작성하지 자바, 그래서 루비의 spacing and naming conventions에 부합하고 있습니다 : 파일 이름이 snake_case되어, 들여 쓰기는 정말 잘못 포맷 된 것 코드를 읽기 어려운이 개 공간, 아니 탭 등입니다 - 여기서 "잘못"은 "비표준"을 의미합니다.

  • 설명이있는 주석 (### Date and Time ###)은 어디에서나 (def date_and_time(array)) 메소드를 추출하고 디버그하기 쉽도록 코드를 작성할 수있는 기회입니다.

+0

시간을내어 주셔서 감사드립니다. 나에게 더 나은 프로그래머를 만드는 것에 대해 정말로 고맙게 생각한다. 실행 가능한 코드를 포함시키는 것은 훌륭한 아이디어이며, 나는 사람들의 90 %가 그렇게하지 않을 것이라고 생각합니다. 또한 변수를 할당하는 것이 문제가되지 않는다는 것이 맞습니다. 주석 처리를 취소하고 "nodeparent = blockProcessor (a)"행을 다시 코딩하여 오류를 표시하고 사라지게 만들 수 있습니다. –

관련 문제