How do I use Mechanize to go through each link? - ruby

Am trying to go through a series of links with a css class title and click those links and then get the product title. But i keep getting the error undefined method each for #<Mechanize::Page::Link:0x007fbfe2524410> (NoMethodError)? I Don't understand what am doning wrong?
heres my code:
require 'mechanize'
file = File.new("outputscrape.txt", 'w')
agent = Mechanize.new { |agent|
agent.user_agent_alias = 'Windows Chrome'}
page = agent.get('http://www.amazon.com/s/ref=sr_nr_n_0?rh=n%3A283155%2Cn%3A%211000%2Cn%3A5%2Cn%3A15377001%2Cn%3A6133979011%2Cn%3A6133980011&bbn=6133979011&ie=UTF8&qid=1412193262&rnid=6133979011')
title_link = page.link_with(:dom_class => "title")
title_link.each do |link|
link.click
file.write(link.at('#productTitle').text.strip)
end

From the mechanize docs:
link_with(criteria)
Find a single link matching criteria.
You need to use:
links_with(criteria)
Find all links matching criteria.
The object mentioned in your error message, Page::Link:
undefined method each for #<Mechanize::Page::Link:0x007fbfe2524410>
(NoMethodError)
doesn't sound like more than one thing, does it? More than one thing would be more like Page::Links, or Page::Link::Group, or Page::LinkSet. You are doing the equivalent of:
10.each do |number|
puts number
end
However, numbers do not have an each() method, so that produces the error:
undefined method `each' for 10:Fixnum (NoMethodError)
Compare that to your error:
undefined method each for #<Mechanize::Page::Link:0x007fbfe2524410>
On the other hand an Array does have an each() method, so you can do this:
[10, 20, 30].each do |number|
puts number
end

Related

Why does this ruby mechanize code throw undefined method?

I'm picking up ruby mechanize & getting tripped up from the start...
Why does this code:
#!/usr/bin/ruby env
require 'rubygems'
require 'mechanize'
agent = Mechanize.new
page = agent.get('http://linkedin.com/')
#pp page
form = page.form.first
#form.fields.each { |f| puts f.name }
#pp page
spit out...
/home/ubuntu/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/mechanize-2.7.4/lib/mechanize/form.rb:217:in `method_missing': undefined method `first' for #<Mechanize::Form:0x007f9f2cf1ced0> (NoMethodError)
from 1-li.rb:10:in `<main>'
You want to use the forms method instead of the form method.
Per the documentation, the forms method returns "a list of all form tags", and you can then method-chain a first method. For example:
require 'mechanize'
mechanize = Mechanize.new
page = mechanize.get('http://www.w3schools.com/html/html_forms.asp')
forms = page.forms
forms.class #=> Array
form = forms.first
form.class #=> Mechanize::Form
To get the first form on the page, use use page.form or page.forms.first

Getting undefined error in mass text app

I'm creating a app that sends mass texts using a JSON file with the numbers and names. Every time I test load the app in IRB I get the error:
NameError: undefined local variable or method `data_from_file' for main:Object
from /home/qc/tep/Coding Stuff/Ruby/text app/main.rb:14:in `contacts_from_file'
I understand what the error means, but I don't understand why I'm getting the error, here's the source code:
require 'json'
def sanatize(numbers)
"+1" + number.gsub(/^1|\D/, "")
end
def numbers_from_file
file = open('numbers.json').read
JSON.parse(file)
end
def contacts_from_file
contacts= { }
data_from_file['feed']['entry'].each do |entry|
name = entry['gsx$name']['$t']
number = entry['gsx$number']['$t']
contacts[sanatize(number)] = name
end
contacts
end
def contact_numbers
contacts_from_file.keys
end
def contact_name
contacts_from_file[number]
end
And here's the JSON file:
{
'1**********' => 'Big Bird'
'1**********'} => 'Josh'
}
If anybody could help me and tell me why the data_from_file is "undefined" it would be extremely helpful, thank you ahead of time.
You never define data_from_file, you just try to read from it in the contects_from_file method.
Perhaps you meant numbers_from_file instead of data_from_file?

undefined method `[]' for nil:NilClass while using Nokogiri

I am using Nokogiri to scrape data from a HTML document, but I'm running into the following error:
`block in <main>': undefined method `[]' for nil:NilClass (NoMethodError)
This is the code to reproduce the problem:
require 'rubygems'
require 'nokogiri'
require 'open-uri'
url = "http://www.somewebsite.com/somepage/some"
doc = Nokogiri::HTML(open(url))
puts doc.at_css("title").text
doc.css(".Info_listing").each do |x|
puts x.at_css(".MoreInfo")[:href]
end
Does anyone know why I'm getting this error?
at_css will return nil if there's no matching element.
If you want to get MoreInfo class element inside Info_listing-class element, you'd better to use following code:
doc.css(".Info_listing .MoreInfo").each do |x|
puts x[:href]
end

Error in first attempt Ruby webcrawler

I am creating a basic scraper that gets the total relief amount rewarded to each state and then displays it, but I'm receiving an error I don't understand. Can you help me fix my program please?
require 'rubygems'
require 'crack'
require 'open-uri'
URL = 'http://www.recovery.gov/pages/GetXmlData.aspx?data=recipientHomeMap'
Crack::XML.parse(open(URL).read)['totals']['state'].each do |state|
puts ['id', 'awarded', 'received', 'jobs'].map{|f| state[f]}.join(', ')
end
rb:7:in ' : undefined method '[]' for nil:NilClass(NoMethodError)
Check what Crack::XML.parse(open(URL).read) return
You aren't getting anything back from Crack::XML.parse(open(URL).read)
You are trying to access values from nil hence the undefined method '[]' for nil:NilClass
Make sure you are actually getting the file first.

Undefined method `name' for nil:NilClass (NoMethodError) when running script

When I run the following script to retrieve the first page of google results
#!/usr/bin/env ruby
require 'rubygems'
require 'nokogiri'
require 'open-uri'
doc = Nokogiri::HTML(open('http://www.google.co.uk/search?q=stackoverflow'))
doc.css('div.vsc').each do |element|
puts element.at_css("h3.r a.l").content
end
I get a undefined methodcontent' for nil:NilClass (NoMethodError)`
How could I solve that? Or at least how could avoid it showing when executing?
As Dave Newton already pointed out in his comment, the result of at_css("h3.r a.l") is nil in your case. Neither the NilClass nor the object nil have a method content.
Workaround:
doc.css('div.vsc').each do |element|
next unless elem = element.at_css("h3.r a.l")
puts elem.content
end

Resources