2012-09-29 4 views
0

Ceci est ma première tentative d'analyse d'une page Web à l'aide de Nokogiri. J'essaie d'extraire les adresses d'une page Web et de les stocker dans un fichier CSV. Jusqu'ici, j'ai seulement pu extraire les champs City, State et Zip.Utilisation de Nokogiri pour extraire les composants d'adresse facultatifs

Je ne sais pas comment extraire le nom de l'installation, l'adresse, le téléphone, les numéros et les informations sur la société. L'adresse peut contenir un ou deux composants de rue.

Pour le téléphone, il peut y avoir un ou plusieurs numéros de téléphone. Les numéros de téléphone peuvent être des numéros normaux ou des numéros de télécopie, mais ils sont seulement indiqués dans le texte plutôt que dans une étiquette. Pour l'entreprise, j'aimerais pouvoir extraire l'URL et le nom.

Chaque adresse sur la page est jointe comme suit:

<!-- address entry --> 

    <div id='1234' class='address'> 

    <div class='address_header'> 
     <h1 class='header_name'> 
     <strong><a href='{URL}'>Facility Name</a></strong> 
     </h1> 
     <h2 class='header_city'> 
     New York 
     </h2> 
    </div> 

    <div class='address_details'> 
     <div class='info'> 
     <p class='address'> 
     <span class='street'>123 ABC St</span><br /> 
     <span class='street'>Unit 1</span><br /> 
     <span class='city'>New York</span>, 
      <span class='state'>NY</span> 
      <span class='zip'>10022</span> 
     </p> 
     <p class='phone'> 
      Phone: <span class='tel'>999.999.9999</span> 
     </p> 
     <p class='phone'> 
      Fax: <span class='tel'>888.888.8888</span> 
     </p> 
     <p class='company'> 
      Company: <a href='{URL}'>Company Name</a> 
     </p> 
     </div> 
    </div> 
    </div> 
    <!-- address entry --> 

    <!-- address entry --> 

    <div id='4567' class='address'> 

    <div class='address_header'> 
     <h1 class='header_name'> 
     <strong><a href='{URL}'>Facility Name</a></strong> 
     </h1> 
     <h2 class='header_city'> 
     New York 
     </h2> 
    </div> 

    <div class='address_details'> 
     <div class='info'> 
     <p class='address'> 
     <span class='street'>456 DEF Rd</span><br /> 
     <span class='city'>New York</span>, 
      <span class='state'>NY</span> 
      <span class='zip'>10022</span> 
     </p> 
     <p class='phone'> 
      Phone: <span class='tel'>555.555.5555</span> 
     </p> 
     <p class='company'> 
      Company: <a href='{URL}'>Company Name</a> 
     </p> 
     </div> 
    </div> 
    </div> 
    <!-- address entry --> 

Voici mon set-up très basique.

require 'nokogiri' 
require 'open-uri' 
require 'csv' 

doc = Nokogiri::HTML(open('[URL]')) 

Cities = Array.new 
States = Array.new 
Zips = Array.new 

doc.css("p[class='address']").css("span[class='city']").each do |city| 
    Cities << city.content 
end 

doc.css("p[class='address']").css("span[class='state']").each do |state| 
    States << state.content 
end 

doc.css("p[class='address']").css("span[class='zip']").each do |zip| 
    Zips << zip.content 
end 

CSV.open("myCSV.csv", "wb") do |row| 
    row << ["City", "State", "Zip"] 
    (0..Cities.length - 1).each do |index| 
    row << [Cities[index], States[index], Zips[index]] 
    end 
end 

Le stockage des informations dans des tableaux séparés semble ici très grossier. Je essentiellement faire une entrée de ligne dans une table CSV pour chaque occurrence du noeud d'adresse dans le document source, puis le remplir avec des champs si elles existent:

Facility St_1 St_2 City State Zip Phone Fax URL Company 
======== ===== ===== ===== ====== ==== ====== ==== ==== ============ 
xxxxxxxx xxxx  xxxx xxxxx xxxx xxxxx  xxxx xxxxxxxx 
xxxxxxxx xxxx xxxxx xxxx xxxxx xxxx xxxxx xxxx xxxx xxxxxxxx 

quelqu'un peut me aider?

Répondre

0

Vous avez probablement des cas de pointe que cela ne traitera pas, mais cela prend soin de votre exemple. Vous devrez changer le document à lire à partir de la page réelle au lieu du segment de données, et vous devrez changer le fichier csv pour l'imprimer dans un fichier au lieu de l'afficher en ligne comme je l'ai fait.

require 'nokogiri' 
require 'open-uri' 
require 'csv' 

doc = Nokogiri::HTML(DATA.read) 

CompanyInfo = Struct.new :facility, :street1, :street2, :city, :state, :zip, :phone, :fax, :url, :company 
company_infos = [] 

doc.css("div.address").each do |address_div| 
    facility   = address_div.at_css('.address_header .header_name').text.strip 
    info    = address_div.css('div.address_details .info') 
    street1, street2 = info.css('.street').map(&:text) 
    city    = info.at_css('.city').text 
    state   = info.at_css('.state').text 
    zip    = info.at_css('.zip').text 
    phone, fax  = info.css('.phone .tel').map(&:text) 
    url    = info.at_css('.company a')['href'] 
    company   = info.at_css('.company a').text 

    company_infos << CompanyInfo.new(facility, street1, street2, city, state, zip, phone, fax, url, company) 
end 

csv = CSV.generate do |csv| 
    csv << %w[Facility Street1 Street2 City State Zip Phone Fax URL Company] 
    company_infos.each do |company_info| 
    csv << company_info.to_a 
    end 
end 

csv # => "Facility,Street1,Street2,City,State,Zip,Phone,Fax,URL,Company\nFacility Name,123 ABC St,Unit 1,New York,NY,10022,999.999.9999,888.888.8888,{URL},Company Name\n" 


__END__ 
<!-- address entry --> 

<div id='1234' class='address'> 

    <div class='address_header'> 
    <h1 class='header_name'> 
     <strong><a href='{URL}'>Facility Name</a></strong> 
    </h1> 
    <h2 class='header_city'> 
     New York 
    </h2> 
    </div> 

    <div class='address_details'> 
    <div class='info'> 
     <p class='address'> 
     <span class='street'>123 ABC St</span><br /> 
     <span class='street'>Unit 1</span><br /> 
     <span class='city'>New York</span>, 
     <span class='state'>NY</span> 
     <span class='zip'>10022</span> 
     </p> 
     <p class='phone'> 
     Phone: <span class='tel'>999.999.9999</span> 
     </p> 
     <p class='phone'> 
     Fax: <span class='tel'>888.888.8888</span> 
     </p> 
     <p class='company'> 
     Company: <a href='{URL}'>Company Name</a> 
     </p> 
    </div> 
    </div> 
</div> 
+0

C'est ce que j'ai fait, et j'ai aussi beaucoup appris! – regulus

0

Vous demandez beaucoup, mais je vais vous aider à démarrer:

fields = %w{street1 street2 phone fax city state zip} 
doc.search('div.address').each do |div| 
    address = {} 
    address['street1'], address['street2'] = *div.search('span.street').map(&:text) 
    address['phone'], address['fax'] = *div.search('span.tel').map(&:text) 
    ['city', 'state', 'zip'].each{|f| address[f] = div.at("span.#{f}").text} 
    csv << fields.map{|f| address[f]} 
end 
Questions connexes