【问题标题】:Converting HTML Table to a CSV automatically using PHP?使用 PHP 自动将 HTML 表转换为 CSV?
【发布时间】:2012-05-16 22:30:31
【问题描述】:

我只需要使用 PHP 在 csv 中自动转换这个 html 表。 有人可以提供任何想法如何做到这一点? 谢谢。

$table = '<table border="1">
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td>row 1, cell 1</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
</tr>
</table>';

伙计们,我只需要 $table 转换成 .csv 文件,该文件可以使用一些 PHP 函数自动生成。我们可以将该 csv 文件的路径定义为 /test/home/path_to_csv

【问题讨论】:

  • 我搜索了谷歌,但没有找到相关的
  • 我知道这不是您正在寻找的,但您可以将其保存为 xls。并且excel会按预期打开它。
  • 您到底想达到什么目的?您是要解析 HTML 并提取数据还是一次性分析?对于一次性,我会推荐找到here 的信息。对于更通用和自动化的工作,需要解析 HTML - 尝试simple parse。或者,如果 HTML 是固定格式,您可能会很幸运地使用正则表达式刮掉标签并只留下数据。 (例如,将 td 替换为一些字段分隔符)然后,CSV 输出是一件小事。
  • 我不想解析任何东西。我确实有自己的变量 $table,其中包含 html 表格数据。现在我想将该数据转换为 .csv 文件,使用 PHP
  • 为了从 HTML 字符串中获取结构,您需要解析数据(在这种情况下存储在变量中)。然后,您可以提取您感兴趣的信息并将其存储为 CSV

标签: php csv


【解决方案1】:

你可以使用str_get_htmlhttp://simplehtmldom.sourceforge.net/

include "simple_html_dom.php";
$table = '<table border="1">
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td>row 1, cell 1</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
</tr>
</table>';

$html = str_get_html($table);



header('Content-type: application/ms-excel');
header('Content-Disposition: attachment; filename=sample.csv');

$fp = fopen("php://output", "w");

foreach($html->find('tr') as $element)
{
        $th = array();
        foreach( $element->find('th') as $row)  
        {
            $th [] = $row->plaintext;
        }

        $td = array();
        foreach( $element->find('td') as $row)  
        {
            $td [] = $row->plaintext;
        }
        !empty($th) ? fputcsv($fp, $th) : fputcsv($fp, $td);
}


fclose($fp);

【讨论】:

  • 巴巴,我们如何为该 csv 文件定义一些路径以自动保存到例如/test/home/path_to_csv
  • 是的,你可以......你需要做的就是删除标题......并将"php://output"更改为你的路径
  • 感谢您的方法。我会在我的电脑上试试(目前我在手机上),然后告诉你。
  • 糟糕!爸爸,我将 php://output 更改为 /mohan/path_to_csv,当我加载页面时,它给出了几个警告!像 警告:fopen(/mohan/path_to_csv) [function.fopen]: failed to open stream: No such file or directory in C:\wamp\www\mohan\TableToCsv.php on line 29。第 29 行是 $fp = fopen("/mohan/path_to_csv", "w");
  • 嗨,我得到了这张照片i.imgur.com/x2mWb.png 中的 CSV 输出,它在数据之间插入了额外的空白行。可以修复吗?我试过修剪()。但它没有用。
【解决方案2】:

你可以在单独的js文件中使用这个函数:

function exportTableToCSV($table, filename) {

        var $rows = $table.find('tr:has(td)'),

            // Temporary delimiter characters unlikely to be typed by keyboard
            // This is to avoid accidentally splitting the actual contents
            tmpColDelim = String.fromCharCode(11), // vertical tab character
            tmpRowDelim = String.fromCharCode(0), // null character

            // actual delimiter characters for CSV format
            colDelim = '","',
            rowDelim = '"\r\n"',

            // Grab text from table into CSV formatted string
            csv = '"' + $rows.map(function (i, row) {
                var $row = $(row),
                    $cols = $row.find('td');

                return $cols.map(function (j, col) {
                    var $col = $(col),
                        text = $col.text();

                    return text.replace('"', '""'); // escape double quotes

                }).get().join(tmpColDelim);

            }).get().join(tmpRowDelim)
                .split(tmpRowDelim).join(rowDelim)
                .split(tmpColDelim).join(colDelim) + '"',

            // Data URI
            csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);

        $(this)
            .attr({
            'download': filename,
                'href': csvData,
                'target': '_blank'
        });
    }

现在,要启动此功能,您可以使用:

$('.getfile').click(
            function() { 
    exportTableToCSV.apply(this, [$('#thetable'), 'filename.csv']);
             });

其中“getfile”应该是分配给按钮的类,您要在其中添加号召性用语。 (点击此按钮,会出现下载弹窗) 并且“thetable”应该是分配给您要下载的表的 ID。

您也可以更改为自定义文件名以在代码中下载。

【讨论】:

【解决方案3】:

您可以使用数组和正则表达式来做到这一点...见下文

$csv = array();
preg_match('/<table(>| [^>]*>)(.*?)<\/table( |>)/is',$table,$b);
$table = $b[2];
preg_match_all('/<tr(>| [^>]*>)(.*?)<\/tr( |>)/is',$table,$b);
$rows = $b[2];
foreach ($rows as $row) {
    //cycle through each row
    if(preg_match('/<th(>| [^>]*>)(.*?)<\/th( |>)/is',$row)) {
        //match for table headers
        preg_match_all('/<th(>| [^>]*>)(.*?)<\/th( |>)/is',$row,$b);
        $csv[] = strip_tags(implode(',',$b[2]));
    } elseif(preg_match('/<td(>| [^>]*>)(.*?)<\/td( |>)/is',$row)) {
        //match for table cells
        preg_match_all('/<td(>| [^>]*>)(.*?)<\/td( |>)/is',$row,$b);
        $csv[] = strip_tags(implode(',',$b[2]));
    }
}
$csv = implode("\n", $csv);
var_dump($csv);

然后你可以使用file_put_contents()将csv字符串写入文件..

【讨论】:

  • 经典答案。如何处理要放入 CSV 的 HTML 标签?
  • 我只使用 5 年或更长时间前提供的范围。如果你正确地转义你的字符串,它们应该保持它们的列结构。
  • 太棒了!在当前情况下也是有效的答案。 :-)
【解决方案4】:

为了扩展已接受的答案,我这样做了,它允许我按类名忽略列,并处理空白行/列。

您可以使用 str_get_html http://simplehtmldom.sourceforge.net/。只需包含它,然后就可以走了! :)

$html = str_get_html($html); // give this your HTML string

header('Content-type: application/ms-excel');
header('Content-Disposition: attachment; filename=sample.csv');

$fp = fopen("php://output", "w");

foreach($html->find('tr') as $element) {
  $td = array();
  foreach( $element->find('th') as $row) {
    if (strpos(trim($row->class), 'actions') === false && strpos(trim($row->class), 'checker') === false) {
      $td [] = $row->plaintext;
    }
  }
  if (!empty($td)) {
    fputcsv($fp, $td);
  }

  $td = array();
  foreach( $element->find('td') as $row) {
    if (strpos(trim($row->class), 'actions') === false && strpos(trim($row->class), 'checker') === false) {
      $td [] = $row->plaintext;
    }
  }
  if (!empty($td)) {
    fputcsv($fp, $td);
  }
}

fclose($fp);
exit;

【讨论】:

    【解决方案5】:

    如果有人在使用 Baba 的答案,但对添加的额外空白感到头疼,这将起作用:

    include "simple_html_dom.php";
    $table = '<table border="1">
    <tr>
    <th>Header 1</th>
    <th>Header 2</th>
    </tr>
    <tr>
    <td>row 1, cell 1</td>
    <td>row 1, cell 2</td>
    </tr>
    <tr>
    <td>row 2, cell 1</td>
    <td>row 2, cell 2</td>
    </tr>
    </table>';
    
    $html = str_get_html($table);   
    
    $fileName="export.csv";
    header('Content-type: application/ms-excel');
    header("Content-Disposition: attachment; filename=$fileName");
    
    $fp = fopen("php://output", "w");
    $csvString="";
    
    $html = str_get_html(trim($table));
    foreach($html->find('tr') as $element)
    {
    
        $td = array();
        foreach( $element->find('th') as $row)
        {
            $row->plaintext="\"$row->plaintext\"";
            $td [] = $row->plaintext;
        }
        $td=array_filter($td);
        $csvString.=implode(",", $td);
    
        $td = array();
        foreach( $element->find('td') as $row)
        {
            $row->plaintext="\"$row->plaintext\"";
            $td [] = $row->plaintext;
        }
        $td=array_filter($td);
        $csvString.=implode(",", $td)."\n";
    }
    echo $csvString;
    fclose($fp);
    exit;
    

    }

    【讨论】:

      【解决方案6】:

      我已经根据在这个线程上找到的代码改编了一个简单的类,现在可以处理colspanrowspan。没有经过大量测试,我相信它可以优化。

      用法:

      require_once('table2csv.php');
      
      $table = '<table border="1">
          <tr>
          <th colspan=2>Header 1</th>
          </tr>
          <tr>
          <td>row 1, cell 1</td>
          <td>row 1, cell 2</td>
          </tr>
          <tr>
          <td>row 2, cell 1</td>
          <td>row 2, cell 2</td>
          </tr>
          <tr>
          <td rowspan=2>top left row</td>
          <td>top right row</td>
          </tr>
          <tr>
          <td>bottom right</td>
          </tr>
          </table>';
      
      table2csv($table,"sample.csv",true);
      

      table2csv.php

      <?php
      
          //download @ http://simplehtmldom.sourceforge.net/
          require_once('simple_html_dom.php');
          $repeatContentIntoSpannedCells = false;
      
      
          //--------------------------------------------------------------------------------------------------------------------
      
          function table2csv($rawHTML,$filename,$repeatContent) {
      
              //get rid of sups - they mess up the wmus
              for ($i=1; $i <= 20; $i++) { 
                  $rawHTML = str_replace("<sup>".$i."</sup>", "", $rawHTML);
              }
      
              global $repeatContentIntoSpannedCells;
      
              $html = str_get_html(trim($rawHTML));
              $repeatContentIntoSpannedCells = $repeatContent;
      
              //we need to pre-initialize the array based on the size of the table (how many rows vs how many columns)
      
              //counting rows is easy
              $rowCount = count($html->find('tr'));
      
              //column counting is a bit trickier, we have to iterate through the rows and basically pull out the max found
              $colCount = 0;
              foreach ($html->find('tr') as $element) {
      
                  $tempColCount = 0;
      
                  foreach ($element->find('th') as $cell) {
                      $tempColCount++;
                  }
      
                  if ($tempColCount == 0) {
                      foreach ($element->find('td') as $cell) {
                          $tempColCount++;
                      }
                  }
      
                  if ($tempColCount > $colCount) $colCount = $tempColCount;
              }
      
              $mdTable = array();
      
              for ($i=0; $i < $rowCount; $i++) { 
                  array_push($mdTable, array_fill(0, $colCount, NULL));
              }
      
              //////////done predefining array
      
              $rowPos = 0;
              $fp = fopen($filename, "w");
      
              foreach ($html->find('tr') as $element) {
      
                  $colPos = 0;
      
                  foreach ($element->find('th') as $cell) {
                      if (strpos(trim($cell->class), 'actions') === false && strpos(trim($cell->class), 'checker') === false) {
                          parseCell($cell,$mdTable,$rowPos,$colPos);
                      }
                      $colPos++;
                  }
      
                  foreach ($element->find('td') as $cell) {
                      if (strpos(trim($cell->class), 'actions') === false && strpos(trim($cell->class), 'checker') === false) {
                          parseCell($cell,$mdTable,$rowPos,$colPos);
                      }
                      $colPos++;
                  }   
      
                  $rowPos++;
              }
      
      
              foreach ($mdTable as $key => $row) {
      
                  //clean the data
                  array_walk($row, "cleanCell");
                  fputcsv($fp, $row);
              }
          }
      
      
          function cleanCell(&$contents,$key) {
      
              $contents = trim($contents);
      
              //get rid of pesky &nbsp's (aka: non-breaking spaces)
              $contents = trim($contents,chr(0xC2).chr(0xA0));
              $contents = str_replace("&nbsp;", "", $contents);
          }
      
      
          function parseCell(&$cell,&$mdTable,&$rowPos,&$colPos) {
      
              global $repeatContentIntoSpannedCells;
      
              //if data has already been set into the cell, skip it
              while (isset($mdTable[$rowPos][$colPos])) {
                  $colPos++;
              }
      
              $mdTable[$rowPos][$colPos] = $cell->plaintext;
      
              if (isset($cell->rowspan)) {
      
                  for ($i=1; $i <= ($cell->rowspan)-1; $i++) {
                      $mdTable[$rowPos+$i][$colPos] = ($repeatContentIntoSpannedCells ? $cell->plaintext : "");
                  }
              }
      
              if (isset($cell->colspan)) {
      
                  for ($i=1; $i <= ($cell->colspan)-1; $i++) {
      
                      $colPos++;
                      $mdTable[$rowPos][$colPos] = ($repeatContentIntoSpannedCells ? $cell->plaintext : "");
                  }
              }
          }
      
      ?>
      

      【讨论】:

        【解决方案7】:

        Baba 的回答包含额外的空格。所以,我将代码更新为:

        include "simple_html_dom.php";
        $table = '<table border="1">
        <tr>
        <th>Header 1</th>
        <th>Header 2</th>
        </tr>
        <tr>
        <td>row 1, cell 1</td>
        <td>row 1, cell 2</td>
        </tr>
        <tr>
        <td>row 2, cell 1</td>
        <td>row 2, cell 2</td>
        </tr>
        </table>';
        
        $html = str_get_html($table);
        
        
        
        header('Content-type: application/ms-excel');
        header('Content-Disposition: attachment; filename=sample.csv');
        
        $fp = fopen("php://output", "w");
        
        foreach($html->find('tr') as $element)
        {
            $td = array();
        foreach( $element->find('th') as $row)
        {
            $td [] = $row->plaintext;
        }
        
        foreach( $element->find('td') as $row)
        {
            $td [] = $row->plaintext;
        }
        fputcsv($fp, $td);
        }
        
        
        fclose($fp);

        【讨论】:

          【解决方案8】:

          假设 out_str 有你的 html 表格数据

          $csv = $out_str;
                  $csv = str_replace("<table class='gradienttable'>","",$csv);
                  $csv = str_replace("</table>","",$csv);
                  $csv = str_replace("</td><td>",",",$csv);
                  $csv = str_replace("<td>","",$csv);
                  $csv = str_replace("</td>","",$csv);
                  $csv = str_replace("</font>","",$csv);
                  $csv = str_replace("</tr>","",$csv);
                  $csv = str_replace("<tr>","\n",$csv);
          

          从文件中删除所有 CSS

                  $csv = str_replace("<font color='yellow'>","",$csv);
                  $csv = str_replace("<font color='red'>","",$csv);
                  $csv = str_replace("<font color='green'>","",$csv);
                  $csv = str_replace("</th><th>",",",$csv);
                  $csv = str_replace("<th>","",$csv);
                  $csv = str_replace("</th>","",$csv);
          
                  file_put_contents('currentFile.csv',$csv);
          

          将文件 currentFile.csv 输出给用户

          希望对你有帮助!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-03-10
            • 1970-01-01
            • 1970-01-01
            • 2012-06-05
            • 1970-01-01
            相关资源
            最近更新 更多