Как я могу преобразовать таблицу HTML в CSV? - PullRequest
41 голосов
/ 10 сентября 2009

Как мне преобразовать содержимое таблицы HTML (<table>) в формат CSV? Есть ли библиотека или программа Linux, которая делает это? Это похоже на копирование таблиц в Internet Explorer и вставку их в Excel.

Ответы [ 15 ]

44 голосов
/ 10 сентября 2009

Этот метод на самом деле не библиотека или программа, но для специальных преобразований вы можете

  • поместите HTML-код для таблицы в текст файл с именем something.xls
  • открыть с помощью электронной таблицы
  • сохранить как CSV.

Я знаю, что это работает с Excel, и я думаю, что я сделал это с электронной таблицей OpenOffice.

Но вы, вероятно, предпочли бы сценарий Perl или Ruby ...

20 голосов
/ 17 апреля 2012

Извините, что воскресил древнюю ветку, но недавно я хотел это сделать, но я хотел, чтобы это сделал 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, но вы можете с такой же легкостью использовать источник таблицы из других источников.

Вот объяснение:

Получить содержимое URL с помощью cURL, сбросить 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'

.

Обратите внимание, что если в какой-либо из ячеек таблицы содержатся запятые, вам может понадобиться сначала их экранировать или использовать другой разделитель.

Надеюсь, это кому-нибудь поможет!

18 голосов
/ 10 сентября 2009

Вот скрипт 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

Работал для моего базового теста.

9 голосов
/ 09 июля 2015

Вот небольшая программа на 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()) 
6 голосов
/ 10 сентября 2009

Я не уверен, что для этого есть готовая библиотека, но если вы хотите испачкать руки небольшим Perl, вы, вероятно, можете что-то сделать с Text::CSV HTML::Parser.

5 голосов
/ 06 ноября 2013

Предполагая, что вы разработали 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 голосов
/ 10 сентября 2009

В Perl вы можете использовать модуль HTML::TableExtract для извлечения данных из таблицы, а затем использовать Text::CSV_XS для создания файла CSV или Spreadsheet::WriteExcel для создания файла Excel.

4 голосов
/ 03 августа 2017

Вот простое решение без какой-либо внешней библиотеки:

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

у меня работает без проблем

4 голосов
/ 09 декабря 2016

Просто чтобы добавить к этим ответам (как я недавно пытался подобную вещь) - если Таблицы Google - это ваша программа для работы с электронными таблицами. Просто сделайте эти две вещи.

1. Уберите все из вашего html-файла вокруг тегов открытия / закрытия таблицы и сохраните его как другой html-файл.

2. Импортируйте этот HTML-файл непосредственно в электронные таблицы Google, и ваша информация будет прекрасно импортирована (Совет: если вы использовали встроенные стили в своей таблице, они также будут импортированы !)

Сэкономила мне кучу времени и выяснила разные преобразования.

3 голосов
/ 06 сентября 2011

На основе ответа audiodude , но упрощено с помощью встроенной библиотеки 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

Мне было интересно, есть ли способ взять NodeSet Nokogiri (row.xpath('td')) и записать это как массив в файл csv за один шаг. Но я мог понять, как сделать это, перебирая каждую ячейку и создавая временный массив содержимого каждой ячейки.

...