Comment convertir le contenu d'un tableau HTML (<table>
) au format CSV? Existe-t-il une bibliothèque ou un programme linux qui fait cela? Cette procédure est similaire à la copie de tableaux dans Internet Explorer et à leur collage dans Excel.
Cette méthode n'est pas vraiment une bibliothèque OR un programme, mais vous pouvez utiliser des conversions ad hoc.
Je sais que cela fonctionne avec Excel et je pense l'avoir fait avec le tableur OpenOffice.
Mais vous préféreriez probablement un script Perl ou Ruby ...
Désolé de ressusciter un ancien fil de discussion, mais je voulais récemment le faire, mais je voulais un script bash 100% portable pour le faire. Alors, voici ma solution en utilisant seulement grep et sed.
La base ci-dessous a été détruite très rapidement et pourrait donc être rendue beaucoup plus élégante, mais je commence tout juste à utiliser sed/awk, etc.
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'
Comme vous pouvez le constater, la source de la page utilise curl, mais vous pouvez tout aussi facilement insérer la source de la table à partir d’autres sources.
Voici l'explication:
Obtenez le contenu de l'URL à l'aide de cURL, dump stderr to null (aucun indicateur de progression)
curl "http://www.webpagewithtableinit.com/" 2>/dev/null
.
Je ne veux que des éléments de table (ne renvoie que des lignes avec les balises TABLE, TR, TH, TD)
| grep -i -e '</\?TABLE\|</\?TD\|</\?TR\|</\?TH'
.
Supprimez les espaces au début de la ligne.
| sed 's/^[\ \t]*//g'
.
Supprimer les nouvelles lignes
| tr -d '\n\r'
.
Remplacer </TR>
par newline
| sed 's/<\/TR[^>]*>/\n/Ig'
.
Supprimer les balises TABLE et TR
| sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig'
.
Supprimer ^<TD>
, ^<TH>
, </TD>$
, </TH>$
| sed 's/^<T[DH][^>]*>\|<\/\?T[DH][^>]*>$//Ig'
.
Remplacer </TD><TD>
par une virgule
| sed 's/<\/T[DH][^>]*><T[DH][^>]*>/,/Ig'
.
Notez que si l'une des cellules du tableau contient des virgules, vous devrez peut-être les échapper en premier ou utiliser un délimiteur différent.
J'espère que cela aide quelqu'un!
Voici un script Ruby qui utilise 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
Travaillé pour mon cas de test de base.
Voici un court programme Python que j'ai écrit pour effectuer cette tâche. Cela a été écrit en quelques minutes, donc ça peut probablement être amélioré. Vous ne savez pas comment il gérera les tables imbriquées (probablement les mauvaises choses) ou plusieurs tables (elles n'apparaîtront probablement que l'une après l'autre) Il ne gère pas colspan
ou rowspan
. Enjoy.
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())
Je ne sais pas s'il existe une bibliothèque préconfigurée pour cela, mais si vous êtes prêt à vous salir les mains avec un peu de Perl, vous pourriez probablement faire quelque chose avec Text::CSV
et HTML::Parser
.
Avec Perl, vous pouvez utiliser le module HTML::TableExtract
pour extraire les données de la table puis utiliser Text::CSV_XS
pour créer un fichier CSV ou Spreadsheet::WriteExcel
pour créer un fichier Excel.
En supposant que vous ayez conçu une page html contenant un tableau, je recommanderais cette solution. Travaillé comme un charme pour moi.
$(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();
});
});
Courtesy: http://www.kubilayerdogan.net/?p=218
Vous pouvez modifier le format de fichier au format .csv ici a.download = 'table_exportée_' + suffixe + '.csv';
Juste pour ajouter à ces réponses (comme je viens de tenter une chose similaire) - si feuilles de calcul Google est votre programme de feuille de calcul de choix. Faites simplement ces deux choses.
1. Supprimez tout le contenu de votre fichier html autour du Balises d'ouverture/fermeture de table et réenregistrez-le sous un autre fichier html.
2. Importez ce fichier html directement dans des feuilles de calcul Google pour une superbe importation de vos informations (Astuce: si vous avez utilisé des styles en ligne dans votre tableau, ils seront également importés!)
M'a fait gagner beaucoup de temps et comprendre différentes conversions.
Voici une solution simple sans aucune bibliothèque externe:
http://www.codexworld.com/export-html-table-data-to-csv-using-javascript/
Cela fonctionne pour moi sans aucun problème
Basé sur la réponse d'audiodude , mais simplifiée en utilisant la bibliothèque CSV intégrée
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
Je me suis demandé s'il y avait un moyen de prendre le Nokogiri NodeSet (row.xpath('td')
) et de l'écrire sous forme de tableau dans le fichier CSV en une seule étape. Mais je ne pouvais le faire qu'en parcourant chaque cellule et en construisant un tableau temporaire du contenu de chaque cellule.
Voici un exemple utilisant pQuery et 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;
L'exemple extrait simplement toutes les balises tr trouvées dans un fichier Excel. Vous pouvez facilement l’adapter pour choisir table ou même déclencher un nouveau fichier Excel par balise table.
Autres points à considérer:
Pour savoir si rowspan ou colspan est utilisé, vous pouvez:
pQuery( $data )->find( 'td' )->each( sub{
my $number_of_cols_spanned = $_->getAttribute( 'colspan' );
});
OpenOffice.org peut afficher les tableaux HTML. Utilisez simplement la commande open du fichier HTML ou sélectionnez et copiez le tableau dans votre navigateur, puis Coller spécial dans OpenOffice.org. Il vous demandera le type de fichier, dont HTML. Sélectionnez ça et le tour est joué!
C’est un très vieux sujet, mais il se peut que quelqu'un comme moi se heurte dessus . J'ai ajouté quelques ajouts pour que le script audiodude lise le fichier HTML à partir du fichier et l’ajoute au code un autre paramètre qui contrôle l’impression des lignes d’en-tête.
le script devrait être exécuté comme ça
Ruby <script_name> <file_name> [<print_headers>]
le code est:
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
Ceci est basé sur la réponse des atomicules mais plus succincte et traite également les cellules th
(en-tête) ainsi que les cellules td
. J'ai également ajouté la méthode strip
pour supprimer les espaces blancs supplémentaires.
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
Envelopper le code dans le bloc CSV garantit que le fichier sera fermé correctement.
Si vous voulez juste le texte et n'avez pas besoin de l'écrire dans un fichier, vous pouvez utiliser ceci:
doc.xpath('//table//tr').inject('') do |result, row|
result << row.xpath('th|td').map {|cell| cell.text.strip}.to_csv
end