Невозможно присвоить значение переменной: неопределенный метод `[] 'для nil: NilClass (NoMethodError) - PullRequest
1 голос
/ 29 сентября 2011

Я полностью озадачен этим.

У меня есть следующий код:

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>

1 Ответ

3 голосов
/ 02 октября 2011

Ваша основная проблема в том, что вы не понимаете XPath.(Вы находитесь в хорошей компании; XPath довольно запутанный.) Ваши селекторы просто не соответствуют тому, что, по вашему мнению, они соответствуют.В частности, тот, который взорвется

*/img

должен быть

//img

или что-то в этом роде.

Теперь, , потому что xpathселектор ничего не соответствует, значение этого оператора Ruby

block.at_xpath("*/img")

равно нулю.И nil не поддерживает [], поэтому, когда вы пытаетесь вызвать ["width"], Ruby жалуется с ошибкой undefined method [] for nil:NilClass.

А что касается того, почему он взрывается, только когда вы присваиваете его переменной ... да, на самом деле это не то, что происходит.Вы, вероятно, тоже изменили что-то еще.


А теперь, позвольте мне сделать несколько других, надеюсь, конструктивных критических замечаний по коду:

  • Ваш вопрос, очевидно, был разработан, чтобы сделатьтрудно ответить.В будущем, пожалуйста, выделите код, о котором идет речь, а не просто вставляйте все домашнее задание (или для чего предназначен этот скребок для экрана).

  • Было бы очень здорово, если бы выпревратили его в один исполняемый файл Ruby, который мы можем дословно выполнить на наших компьютерах, например:

.

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

Таким образом, мы сможем отладить наши компьютеры,не только в наших мыслях.

  • Вы пишете Ruby сейчас, а не на Java, так что соблюдайте соглашения о пробелах и именах Ruby : имена файлов - snake_case, отступы -2 пробела, без вкладок и т. Д. Действительно трудно прочитать код, который отформатирован неправильно - где «неправильно» означает «нестандартный».

  • Везде, где есть один из этих описательныхкомментарии (### Date and Time ###) - это возможность извлечь метод (def date_and_time(array)) и сделать ваш код чище и проще для отладки.

...