将HTML格式化为CSV格式

Duc*_*337 0 ruby csv nokogiri

我正在使用Ruby与Nokogiri一起抓取一个网站.

此脚本创建本地文本文件,打开URL,并在tr td满足表达式时写入文件.它工作正常.

require 'rubygems'
require 'nokogiri'
require 'open-uri'

DOC_URL_FILE = "doc.csv" 

url = "http://www.SuperSecretWebSite.com"

data = Nokogiri::HTML(open(url))


all_data = data.xpath('//tr/td').text

File.open(DOC_URL_FILE, 'w'){|file| file.write all_data} 
Run Code Online (Sandbox Code Playgroud)

每行有五个字段,我想水平运行,然后在填充五个单元格后转到下一行.数据全部存在,但不可用.

我希望从知道如何创建CSV格式代码的人那里学习或获取代码:

  1. 当脚本正在读取代码时,将每个新的td/td x5水平转储到它自己的单元格中.
  2. 转到下一行等

HTML的布局是:

<tr>
    <td>John Smith</td>
    <td>I live here 123</td>
    <td>phone ###</td>
    <td>Birthday</td>
    <td>Other Data</td>
</tr>
Run Code Online (Sandbox Code Playgroud)

最终产品应该是什么样子.

http://picpaste.com/pics/Screenshot-KRnqRGrP.1361813552.png
Run Code Online (Sandbox Code Playgroud)

电流输出

    john Smith      I live here 123  phone ### Birthday Other Data,
Run Code Online (Sandbox Code Playgroud)

the*_*Man 5

这是非常标准的代码,用于遍历表并将其单元格提取到数组数组中.您在此处对数据执行的操作取决于您,但将其传递给CSV非常容易.

require 'nokogiri'
require 'pp'

doc = Nokogiri::HTML(<<EOT)
<table>
  <tr>
    <td>John Smith</td>
    <td>I live here 123</td>
    <td>phone ###</td>
    <td>Birthday</td>
    <td>Other Data</td>
  </tr>
  <tr>
    <td>John Smyth</td>
    <td>I live here 456</td>
    <td>phone ###</td>
    <td>Birthday</td>
    <td>Other Data</td>
  </tr>
</table>
EOT

data = []
doc.at('table').search('tr').each do |tr|
  data << tr.search('td').map(&:text)
end

pp data
Run Code Online (Sandbox Code Playgroud)

哪个输出:

[["John Smith", "I live here 123", "phone ###", "Birthday", "Other Data"],
["John Smyth", "I live here 456", "phone ###", "Birthday", "Other Data"]]
Run Code Online (Sandbox Code Playgroud)

代码用于at定位第一个<table>,然后遍历每个<tr>使用search.对于每一行,它遍历单元格并提取其文本.

Nokogiri at发现了第一次出现的东西,并返回一个Node.search查找所有出现的并返回一个NodeSet,它就像一个数组.为简单起见,我使用CSS访问器而不是XPath.


作为一个FYI:

File.open(DOC_URL_FILE, 'w'){|file| file.write all_data} 
Run Code Online (Sandbox Code Playgroud)

可以写得更简洁如下:

File.write(DOC_URL_FILE, all_data)
Run Code Online (Sandbox Code Playgroud)

我一直在研究这个问题.你能给我更多帮助吗?

叹...

您是否阅读过CSV文档,尤其是示例?如果,而不是定义data = []我们用以下内容替换它会发生什么?

CSV.open("path/to/file.csv", "wb") do |data|
Run Code Online (Sandbox Code Playgroud)

并使用CSV块包装循环,如:

CSV.open("path/to/file.csv", "wb") do |data|
  doc.at('table').search('tr').each do |tr|
    data << tr.search('td').map(&:text)
  end
end
Run Code Online (Sandbox Code Playgroud)

这没有经过测试,但它真的那么简单.去吧,摆弄它.

  • 我不打算为你写一个完整的解决方案.阅读[CSV文档](http://ruby-doc.org/stdlib-1.9.3/libdoc/csv/rdoc/CSV.html),它非常清楚地说明了这一点.您只需要弄清楚如何以及在何处正确打开CSV文件并更改代码中的变量.顺便说一下,你的样本输出不是CSV,它是伪柱状的,根本不能用于数据加载. (2认同)