Как преобразовать содержимое таблицы HTML (<table>
) в формат CSV? Есть ли библиотека или программа linux, которая делает это? Это похоже на таблицы копирования в Internet Explorer и вставка их в Excel.
Как преобразовать таблицу HTML в CSV?
Ответ 1
Этот метод на самом деле не является библиотекой или программой, но для ad hoc-конверсий вы можете
- поместите HTML для таблицы в текстовый файл something.xls
- откройте его с помощью таблицы.
- сохранить его как CSV.
Я знаю, что это работает с Excel, и я считаю, что сделал это с помощью электронной таблицы OpenOffice.
Но вы, вероятно, предпочли бы Perl или Ruby script...
Ответ 2
Извините за возрождение древней темы, но я недавно хотел сделать это, но я хотел использовать 100% портативный bash script. Итак, здесь мое решение использует только 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'
Как вы можете видеть, у меня есть источник страницы, использующий завиток, но вы можете так же легко загружать в источник таблицы из другого места.
Вот объяснение:
Получить содержимое URL-адреса с помощью cURL, dump stderr до нуля (без индикатора выполнения)
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'
.
Обратите внимание, что если какая-либо из ячеек таблицы содержит запятые, вам может потребоваться сначала их избежать или использовать другой разделитель.
Надеюсь, это поможет кому-то!
Ответ 3
Здесь ruby script, который использует 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
Работала для моего основного теста.
Ответ 4
Вот короткая программа 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())
Ответ 5
Я не уверен, есть ли для этого предварительно подготовленная библиотека, но если вы хотите, чтобы ваши руки были грязными с небольшим Perl, вы могли бы что-то сделать с Text::CSV
и HTML::Parser
.
Ответ 6
С помощью Perl вы можете использовать модуль HTML::TableExtract
для извлечения данных из таблицы, а затем используйте Text::CSV_XS
для создания файла CSV или Spreadsheet::WriteExcel
для создания файла Excel.
Ответ 7
Предполагая, что u've спроектировал 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';
Ответ 8
Просто добавлю к этим ответам (так как я недавно пытался сделать подобное) - если электронные таблицы Google - ваша программа для работы с электронными таблицами по выбору. Просто выполните эти две вещи.
1. Разделите все содержимое html файла вокруг таблиц открытия/закрытия таблиц и сохраните его как другой файл html.
2. Импортируйте этот html файл непосредственно в электронные таблицы google и вы получите красивую импортную информацию (верхний совет: если вы использовали встроенные стили в своей таблице, они также будут импортированы!)
Сэкономил мне много времени и вычислил разные конверсии.
Ответ 9
Здесь простое решение без какой-либо внешней библиотеки:
https://www.codexworld.com/export-html-table-data-to-csv-using-javascript/
Он работает для меня без каких-либо проблем
Ответ 10
Исходя из audiodude 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 за один шаг. Но я мог только вычислить это, итерации по каждой ячейке и создание временного массива каждого содержимого ячейки.
Ответ 11
здесь несколько вариантов
http://groups.google.com/group/ruby-talk-google/browse_thread/thread/cfae0aa4b14e5560?hl=nn
http://ouseful.wordpress.com/2008/10/14/data-scraping-wikipedia-with-google-spreadsheets/
Ответ 12
Это очень старая нить, но может быть кто-то вроде меня. Я сделал некоторые дополнения для audiodude script, чтобы прочитать html из файла, вместо этого добавив его в код, и еще один параметр, который контролирует печать строк заголовка.
script должен выполняться как
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
Ответ 13
Вот пример, используя pQuery и Таблица:: 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. Вы можете легко адаптировать его, чтобы выбрать конкретную таблицу или даже запустить новый файл excel для каждого тега таблицы.
Дальнейшие действия:
- Вы можете захотеть получить теги td для создания заголовков excel.
- И у вас могут быть проблемы с rowspan и colspan.
Чтобы узнать, используются ли rowspan или colspan, вы можете:
pQuery( $data )->find( 'td' )->each( sub{
my $number_of_cols_spanned = $_->getAttribute( 'colspan' );
});
Ответ 14
OpenOffice.org может просматривать таблицы HTML. Просто используйте команду open в файле HTML или выберите и скопируйте таблицу в своем браузере, а затем вставьте вкладку Special в OpenOffice.org. Он запросит вас для типа файла, одним из которых должен быть HTML. Выберите это и вуаля!
Ответ 15
Это основано на ответе atomicules, но более сжато, а также обрабатывает ячейки th
(header), а также ячейки 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
Ответ 16
Здесь обновленная версия ответа Yuvai, которая правильно обрабатывает поля, требующие цитирования (то есть поля, содержащие запятые в данных, двойные кавычки или несколько строк)
#!/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())
Одним из улучшений этого сценария может быть добавление поддержки для указания другого разделителя строк (или автоматического расчета для платформы-правильного) и другого разделителя столбцов.