web-dev-qa-db-ja.com

HTMLテーブルをCSVに変換するにはどうすればよいですか?

HTMLテーブルのコンテンツ(<table>)CSV形式に?これを行うライブラリまたはLinuxプログラムはありますか?これは、Internet Explorerでテーブルをコピーし、それらをExcelに貼り付けることに似ています。

41
asdfasdf

このメソッドは、実際にはライブラリORプログラムではありませんが、アドホック変換の場合は、

  • テーブルのHTMLをtextというファイルに入れますsomething.xls
  • スプレッドシートで開きます
  • cSVとして保存します。

これがExcelで機能することは知っていますし、OpenOfficeスプレッドシートでこれをやったと思います。

しかし、おそらくPerlまたはRuby script ...

45
pavium

古代のスレッドを復活させてすみませんが、最近これをやりたかったのですが、100%ポータブルなbashスクリプトでそれを実現したかったのです。そこで、grepとsedのみを使用したソリューションを紹介します。

以下は非常に早く打ち消されたので、もっとエレガントにすることができましたが、sed/awkなどで本当に始めたばかりです...

curl "http://www.webpagewithtableinit.com/" 2>/dev/null | grep -i -e '</\?TABLE\|</\?TD\|</\?TR\|</\?TH' | sed 's/^[\ \t]*//g' | tr -d '\n' | sed 's/<\/TR[^>]*>/\n/Ig'  | sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' | sed 's/^<T[DH][^>]*>\|<\/\?T[DH][^>]*>$//Ig' | sed 's/<\/T[DH][^>]*><T[DH][^>]*>/,/Ig'

ご覧のとおり、curlを使用してページソースを取得しましたが、テーブルソースを他の場所から簡単に取り込むことができます。

説明は次のとおりです。

CURLを使用してURLのコンテンツを取得し、stderrをnullにダンプします(進行状況メーターなし)

curl "http://www.webpagewithtableinit.com/" 2>/dev/null 

テーブル要素のみが必要です(TABLE、TR、TH、TDタグのある行のみを返します)

| grep -i -e '</\?TABLE\|</\?TD\|</\?TR\|</\?TH'

行の先頭にある空白を削除します。

| sed 's/^[\ \t]*//g' 

改行を削除する

| tr -d '\n\r' 

</TR>を改行に置き換えます

| sed 's/<\/TR[^>]*>/\n/Ig'  

TABLEおよびTRタグを削除する

| sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' 

^<TD>^<TH></TD>$</TH>$を削除します

| sed 's/^<T[DH][^>]*>\|<\/\?T[DH][^>]*>$//Ig' 

</TD><TD>をコンマに置き換えます

| sed 's/<\/T[DH][^>]*><T[DH][^>]*>/,/Ig'

テーブルセルのいずれかにカンマが含まれている場合は、最初にエスケープするか、別の区切り文字を使用する必要がある場合があります。

これが誰かを助けることを願っています!

21
DRendar

Ruby nokogiriを使用するスクリプト- http://nokogiri.rubyforge.org/nokogiri/

require 'nokogiri'

doc = Nokogiri::HTML(table_string)

doc.xpath('//table//tr').each do |row|
  row.xpath('td').each do |cell|
    print '"', cell.text.gsub("\n", ' ').gsub('"', '\"').gsub(/(\s){2,}/m, '\1'), "\", "
  end
  print "\n"
end

私の基本的なテストケースで働いた。

19
audiodude

ここに短いPythonこのタスクを完了するために書いたプログラムがあります。数分で書かれたので、おそらくより良くすることができます。 「悪いことをする」または複数のテーブル(たぶん次々に表示されます)。colspanまたはrowspanを処理しません。

from HTMLParser import HTMLParser
import sys
import re


class HTMLTableParser(HTMLParser):
    def __init__(self, row_delim="\n", cell_delim="\t"):
        HTMLParser.__init__(self)
        self.despace_re = re.compile(r'\s+')
        self.data_interrupt = False
        self.first_row = True
        self.first_cell = True
        self.in_cell = False
        self.row_delim = row_delim
        self.cell_delim = cell_delim

    def handle_starttag(self, tag, attrs):
        self.data_interrupt = True
        if tag == "table":
            self.first_row = True
            self.first_cell = True
        Elif tag == "tr":
            if not self.first_row:
                sys.stdout.write(self.row_delim)
            self.first_row = False
            self.first_cell = True
            self.data_interrupt = False
        Elif tag == "td" or tag == "th":
            if not self.first_cell:
                sys.stdout.write(self.cell_delim)
            self.first_cell = False
            self.data_interrupt = False
            self.in_cell = True

    def handle_endtag(self, tag):
        self.data_interrupt = True
        if tag == "td" or tag == "th":
            self.in_cell = False

    def handle_data(self, data):
        if self.in_cell:
            #if self.data_interrupt:
            #   sys.stdout.write(" ")
            sys.stdout.write(self.despace_re.sub(' ', data).strip())
            self.data_interrupt = False


parser = HTMLTableParser() 
parser.feed(sys.stdin.read()) 
9
Yuval

このために事前に作成されたライブラリがあるかどうかはわかりませんが、少しのPerlで手を汚したい場合は、おそらく Text::CSV および HTML::Parser

6
Chris Simmons

これらの回答に追加するだけです(最近同様のことを試みています)-Googleスプレッドシートが選択したスプレッドシートプログラムである場合。これら2つのことを行うだけです。

1。 htmlファイルからテーブル開始/終了タグの周りのすべてを取り除き、別のhtmlファイルとして再保存します。

2。 htmlファイルを直接Googleスプレッドシートにインポートすると、情報がきれいにインポートされます(トップヒント:テーブルでインラインスタイルを使用した場合、同様にインポートされます!)

時間を節約して、さまざまなコンバージョンを見つけました。

5
toms.work

Perlでは、 HTML::TableExtract テーブルからデータを抽出してから Text::CSV_XS CSVファイルを作成するか、 Spreadsheet::WriteExcel Excelファイルを作成します。

5
jmcnamara

テーブルを含むhtmlページを設計したと仮定すると、このソリューションをお勧めします。私にとって魅力のように働いた。

$(document).ready(function() {
$("#btnExport").click(function(e) {
    //getting values of current time for generating the file name
    var dt = new Date();
    var day = dt.getDate();
    var month = dt.getMonth() + 1;
    var year = dt.getFullYear();
    var hour = dt.getHours();
    var mins = dt.getMinutes();
    var postfix = day + "." + month + "." + year + "_" + hour + "." + mins;
    //creating a temporary HTML link element (they support setting file names)
    var a = document.createElement('a');
    //getting data from our div that contains the HTML table
    var data_type = 'data:application/vnd.ms-Excel';
    var table_div = document.getElementById('dvData');
    var table_html = table_div.outerHTML.replace(/ /g, '%20');
    a.href = data_type + ', ' + table_html;
    //setting the file name
    a.download = 'exported_table_' + postfix + '.xls';
    //triggering the function
    a.click();
    //just in case, prevent default behaviour
    e.preventDefault();
});
});

礼儀: http://www.kubilayerdogan.net/?p=218

ここでファイル形式を.csvに編集できますa.download = 'exported_table_' + postfix + '.csv';

5
Bhagirath

ここに外部ライブラリのないシンプルなソリューション:

https://www.codexworld.com/export-html-table-data-to-csv-using-javascript/

問題なく動作します

4
Met Kiani

audiodude's answer に基づきますが、組み込みのCSVライブラリを使用して簡略化されています

_require 'nokogiri'
require 'csv'

doc = Nokogiri::HTML(table_string)
csv = CSV.open("output.csv", 'w')

doc.xpath('//table//tr').each do |row|
    tarray = [] #temporary array
    row.xpath('td').each do |cell|
        tarray << cell.text #Build array of that row of data.
    end
    csv << tarray #Write that row out to csv file
end

csv.close
_

Nokogiri NodeSet(row.xpath('td'))を取得し、これをcsvファイルへの配列として1ステップで書き込む方法があるかどうか疑問に思いました。しかし、各セルを反復処理し、各セルのコンテンツの一時的な配列を構築することによって、それを行うことしか理解できませんでした。

3
atomicules
2
Gene T

これは非常に古いスレッドですが、私のような誰かがそれにぶつかる可能性があります。 audiodude のスクリプトに追加して、ファイルからHTMLを読み取る代わりに、コードに追加し、ヘッダー行の印刷を制御する別のパラメーターを追加しました。

スクリプトはそのように実行する必要があります

Ruby <script_name> <file_name> [<print_headers>]

コードは次のとおりです。

require 'nokogiri'

print_header_lines = ARGV[1]

File.open(ARGV[0]) do |f|

  table_string=f
  doc = Nokogiri::HTML(table_string)

  doc.xpath('//table//tr').each do |row|
    if print_header_lines
      row.xpath('th').each do |cell|
        print '"', cell.text.gsub("\n", ' ').gsub('"', '\"').gsub(/(\s){2,}/m, '\1'), "\", "
      end
    end
    row.xpath('td').each do |cell|
      print '"', cell.text.gsub("\n", ' ').gsub('"', '\"').gsub(/(\s){2,}/m, '\1'), "\", "
    end
    print "\n"
  end
end
2
Tata

OpenOffice.orgはHTMLテーブルを表示できます。 HTMLファイルでopenコマンドを使用するか、ブラウザでテーブルを選択してコピーしてから、OpenOffice.orgで形式を選択して貼り付けます。ファイルタイプを照会しますが、その1つはHTMLである必要があります。それを選択して出来上がり!

1
Happy Gilmore

これは atomicules 'answer に基づいていますが、より簡潔で、th(ヘッダー)セルとtdセルも処理します。また、余分な空白を取り除くためにstripメソッドを追加しました。

CSV.open("output.csv", 'w') do |csv|
  doc.xpath('//table//tr').each do |row|
    csv << row.xpath('th|td').map {|cell| cell.text.strip}
  end
end

CSVブロック内にコードをラップすると、ファイルが適切に閉じられます。


テキストだけが必要で、ファイルに書き込む必要がない場合は、これを使用できます。

doc.xpath('//table//tr').inject('') do |result, row|
  result << row.xpath('th|td').map {|cell| cell.text.strip}.to_csv
end
1
Josh

pQuery および Spreadsheet :: WriteExcel を使用した例を次に示します。

use strict;
use warnings;

use Spreadsheet::WriteExcel;
use pQuery;

my $workbook = Spreadsheet::WriteExcel->new( 'data.xls' );
my $sheet    = $workbook->add_worksheet;
my $row = 0;

pQuery( 'http://www.blahblah.site' )->find( 'tr' )->each( sub{
    my $col = 0;
    pQuery( $_ )->find( 'td' )->each( sub{
        $sheet->write( $row, $col++, $_->innerHTML );
    });
    $row++;
});

$workbook->close;

この例では、検出したすべてのtrタグをExcelファイルに単純に抽出します。特定のtableを選択したり、tableタグ。

さらに考慮すべき事項:

  • Excelヘッダーを作成するためにtdタグを取得することができます。
  • また、rowspanおよびcolspanに問題がある場合があります。

Rowspanまたはcolspanが使用されているかどうかを確認するには:

pQuery( $data )->find( 'td' )->each( sub{ 
    my $number_of_cols_spanned = $_->getAttribute( 'colspan' );
});
1
draegtun

Yuvai's answer の更新バージョンは、引用が必要なフィールド(データにコンマを含むフィールド、二重引用符、または複数行にわたるフィールド)を適切に処理します

#!/usr/bin/env python3
from html.parser import HTMLParser
import sys
import re

class HTMLTableParser(HTMLParser):
    def __init__(self, row_delim="\n", cell_delim=","):
        HTMLParser.__init__(self)
        self.despace_re = re.compile("\s+")
        self.data_interrupt = False
        self.first_row = True
        self.first_cell = True
        self.in_cell = False
        self.row_delim = row_delim
        self.cell_delim = cell_delim
        self.quote_buffer = False
        self.buffer = None

    def handle_starttag(self, tag, attrs):
        self.data_interrupt = True
        if tag == "table":
            self.first_row = True
            self.first_cell = True
        Elif tag == "tr":
            if not self.first_row:
                sys.stdout.write(self.row_delim)
            self.first_row = False
            self.first_cell = True
            self.data_interrupt = False
        Elif tag == "td" or tag == "th":
            if not self.first_cell:
                sys.stdout.write(self.cell_delim)
            self.first_cell = False
            self.data_interrupt = False
            self.in_cell = True
        Elif tag == "br":
            self.quote_buffer = True
            self.buffer += self.row_delim

    def handle_endtag(self, tag):
        self.data_interrupt = True
        if tag == "td" or tag == "th":
            self.in_cell = False
        if self.buffer != None:
            # Quote if needed...
            if self.quote_buffer or self.cell_delim in self.buffer or "\"" in self.buffer:
                # Need to quote! First, replace all double-quotes with quad-quotes
                self.buffer = self.buffer.replace("\"", "\"\"")
                self.buffer = "\"{0}\"".format(self.buffer)
            sys.stdout.write(self.buffer)
            self.quote_buffer = False
            self.buffer = None

    def handle_data(self, data):
        if self.in_cell:
            #if self.data_interrupt:
            #   sys.stdout.write(" ")
            if self.buffer == None:
                self.buffer = ""
            self.buffer += self.despace_re.sub(" ", data).strip()
            self.data_interrupt = False

parser = HTMLTableParser() 
parser.feed(sys.stdin.read())

このスクリプトの拡張機能の1つは、異なる行区切り文字(またはプラットフォームに適した区切り文字の自動計算)および異なる列区切り文字の指定のサポートを追加することです。

0
Diego Rivera