0

Nokogiriを使用してWebページを解析するのはこれが初めてです。

Webページからアドレスを抽出してCSVファイルに保存しようとしています。これまでのところ、City、State、およびZipフィールドのみを抽出できました。

施設名、住所、電話番号、番号、会社情報を抽出する方法がわかりません。住所には、1つまたは2つのストリートコンポーネントが含まれる場合があります。

電話の場合、1つ以上の電話番号が存在する場合があります。電話番号は通常の番号でもFAX番号でもかまいませんが、タグではなくテキストでのみ示されます。会社の場合は、URLと名前を抽出できるようにしたいと思います。

ページ上の各アドレスは次のように囲まれています。

  <!-- 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 -->

これが私の非常に基本的な設定です。

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

ここに情報を別々の配列に格納するのは非常に不格好なようです。基本的に、ソースドキュメントでアドレスノードが出現するたびにCSVテーブルに行エントリを作成し、フィールドが存在する場合はフィールドを入力します。

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

誰かが私を助けることができますか?

4

2 に答える 2

0

あなたはたくさんのことを求めていますが、私はあなたを始めましょう:

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
于 2012-09-29T12:23:42.893 に答える
0

あなたはおそらくこれが処理できないいくつかのエッジケースを持っていますが、これはあなたの例の世話をします。データセグメントではなく実際のページから読み取るようにドキュメントを変更する必要があります。また、私が行ったようにインラインで表示するのではなく、ファイルに印刷するようにcsvを変更する必要があります。

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>
于 2012-09-29T14:38:30.800 に答える