定制 bakame/html-table 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

bakame/html-table

Composer 安装命令:

composer require bakame/html-table

包简介

convert html table into a PHP data structure

README 文档

README

Author Software License Build Latest Version Total Downloads Sponsor development of this project

bakame/html-table is a small PHP package that allows you to parse, import and manipulate tabular data represented as HTML Table. Once installed, you will be able to do the following:

use Bakame\TabularData\HtmlTable\Parser;

$table = Parser::new()
    ->tableHeader(['rank', 'move', 'team', 'player', 'won', 'drawn', 'lost', 'for', 'against', 'gd', 'points'])
    ->parseFile('https://www.bbc.com/sport/football/tables');

$table
    ->getTabularData()
    ->filter(fn (array $row) => (int) $row['points'] >= 10)
    ->sorted(fn (array $rowA, array $rowB) => (int) $rowB['for'] <=> (int) $rowA['for'])
    ->fetchPairs('team', 'for');

// returns 
// [
//  "Brighton" => "15"
//  "Man City" => "14"
//  "Tottenham" => "13"
//  "Liverpool" => "12"
//  "West Ham" => "10"
//  "Arsenal" => "9"
// ]

System Requirements

league\csv 9.25.0 library is required. (since version 0.6.0).

Installation

Use composer:

composer require bakame/html-table

Documentation

The Parser can convert a file (a PHP stream or a Path with an optional context like fopen) or an HTML document into a League\Csv\TabularData implementing object. Once converted you can use all the methods and feature made available by the interface (see ResultSet) for more information.

The Parser itself is immutable, whenever you change a configuration option a new instance is returned.

The Parser constructor is private to instantiate the object you are required to use the new method instead

use Bakame\HtmlTable\Parser;

$parser = Parser::new()
    ->ignoreTableHeader()
    ->ignoreXmlErrors()
    ->tableCaption('This is a beautiful table');

parseHtml and parseFile

To extract and parse your table use either the parseHtml or parseFile methods. If parsing is not possible a ParseError exception will be thrown.

use Bakame\HtmlTable\Parser;

$parser = new Parser();

$table = $parser->parseHtml('<table>...</table>');
$table = $parser->parseFile('path/to/html/file.html');

parseHtml parses an HTML page represented by:

  • a string,
  • a Stringable object,
  • a DOMDocument,
  • a DOMElement,
  • or a SimpleXMLElement

whereas parseFile works with:

  • a filepath,
  • or a PHP readable stream.

Both methods return a Table instance which implements the League\Csv\TabularDataReader interface and also give access to the table caption if present via the getCaption method.

use Bakame\HtmlTable\Parser;

$html = <<<HTML
<div>
<table>
    <caption>Songs</caption>
    <thead>
        <tr>
            <th>Title</th>
            <th>Singer</th>
            <th>Country</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Nakei Nairobi</td>
            <td>Mbilia Bel</td>
            <td rowspan="3">DR Congo</td>
        </tr>
        <tr>
            <td>Muvaro</td>
            <td>Zaiko Langa Langa</td>
        </tr>
        <tr>
            <td>Nzinzi</td>
            <td>Emeneya</td>
        </tr>
    </tbody>
</table>
</div>
HTML;

$table = (new Parser())->parseHtml($html);
$table->getCaption(); //returns 'Songs'
$table->getHeader();  //returns ['Title','Singer', 'Country']
$tableData = $table->geTabularData();
$tableData->nth(2); //returns ["Title" => "Nzinzi", "Singer" => "Emeneya", "Country" => "DR Congo"]
json_encode($tableData->slice(0, 1));
//[{"Title":"Nakei Nairobi","Singer":"Mbilia Bel","Country":"DR Congo"}]

Default configuration

By default, when calling the new Parser() the parser will:

  • try to parse the first table found in the page
  • expect the table header row to be the first tr found in the thead section of your table
  • exclude the table thead section when extracting the table content.
  • ignore XML errors.
  • have no formatter attached.
  • have no default caption to be used if none is present in the table.

Each of the following settings can be changed to improve the conversion against your business rules:

tablePosition and tableXpathPosition

Selecting the table to parse in the HTML page can be done using two (2) methods Parser::tablePosition and Parser::tableXpathPosition

If you know the table position in the page in relation with its integer offset or if you know it's id attribute value you should use Parser::tablePosition otherwise favor Parser::tableXpathPosition which expects an xpath expression. If the expression is valid, and a list of table is found, the first result will be returned.

use Bakame\HtmlTable\Parser;

$parser = (new Parser())->tablePosition('table-id'); // parses the <table id='table-id'>
$parser = (new Parser())->tablePosition(3); // parses the 4th table of the page
$parser = (new Parser())->tableXPathPosition("//main/div/table");
//parse the first table that matches the xpath expression

Parser::tableXpathPosition and Parser::tablePosition override each other. It is recommended to use one or the other but not both at the same time.

tableCaption

You can optionally define a caption for your table if none is present or found during parsing.

use Bakame\HtmlTable\Parser;

$parser = (new Parser())->tableCaption('this is a generated caption');
$parser = (new Parser())->tableCaption(null);  // remove any default caption set

tableHeader, tableHeaderPosition, ignoreTableHeader and resolveTableHeader

The following settings configure the Parser in relation to the table header. By default, the parser will try to parse the first tr tag found in the thead section of the table. But you can override this behaviour using one of these settings:

tableHeaderPosition

Tells where to locate and resolve the table header

use Bakame\HtmlTable\Parser;
use Bakame\HtmlTable\Section;

$parser = (new Parser())->tableHeaderPosition(Section::Thead, 3);
// header is the 4th row in the <thead> table section

The method uses the Bakame\HtmlTable\Section enum to designate which table section to use to resolve the header

use Bakame\HtmlTable\Section;

enum Section
{
    case thead;
    case tbody;
    case tfoot;
    case tr;
}

If Section::tr is used, tr tags will be used independently of their section. The second argument is the table header tr offset; it defaults to 0 (ie: the first row).

ignoreTableHeader and resolveTableHeader

Instructs the parser to resolve or not the table header using tableHeaderPosition configuration. If no resolution is done, no header will be included in the returned Table instance.

use Bakame\HtmlTable\Parser;

$parser = (new Parser())->ignoreTableHeader();  // no table header will be resolved
$parser = (new Parser())->resolveTableHeader(); // will attempt to resolve the table header

tableHeader

You can directly specify the header of your table and override any other table header related configuration with this configuration

use Bakame\HtmlTable\Parser;
use Bakame\HtmlTable\Section;

$parser = (new Parser())->tableHeader(['rank', 'team', 'winner']);

If you specify a non-empty array as the table header, it will take precedence over any other table header related options.

Because it is tabular data, each cell MUST be unique otherwise an exception will be thrown

You can skip or re-arrange the source columns by skipping them by their offsets and/or by re-ordering the offsets.

use Bakame\HtmlTable\Parser;
use Bakame\HtmlTable\Section;

$parser = (new Parser())->tableHeader([3 => 'rank',  7 => 'winner', 5 => 'team']);
// only 3 columns will be extracted the 4th, 6th and 8th columns
// and re-arrange as 'rank' first and 'team' last
// if a column is missing its value will be PHP `null` type

includeSection and excludeSection

Tells which section should be parsed based on the Section enum

use Bakame\HtmlTable\Parser;
use Bakame\HtmlTable\Section;

$parser = (new Parser())->includeSection(Section::Tbody);  // thead and tfoot are included during parsing
$parser = (new Parser())->excludeSection(Section::Tr, Section::Tfoot); // table direct tr children and tfoot are not included during parsing

By default, the thead section is not parse. If a thead row is selected to be the header, it will be parsed independently of this setting.

⚠️Tips: to be sure of which sections will be modified, first remove all previous settings before applying your configuration as shown below:

- (new Parser())->includeSection(Section::tbody);
+ (new Parser())->excludeSection(...Section::cases())->includeSection(Section::tbody);

The first call will still include the tfoot and the tr sections, whereas the second call removes any previous setting guaranting that only the tbody if present will be parsed.

withFormatter and withoutFormatter

Add or remove a record formatter applied to the data extracted from the table before you can access it. The header is not affected by the formatter if it is defined.

use Bakame\HtmlTable\Parser;

$parser = (new Parser())->withFormatter($formatter); // attach a formatter to the parser
$parser = (new Parser())->withFormatter(null);       // removed the attached formatter if it exists

The formatter closure signature should be:

function (array $record): array;

If a header was defined or specified, the submitted record will have the header definition set; otherwise an array list is provided.

The following formatter will work on any table content as long as it is defined as a string.

$formatter = fn (array $record): array => array_map(strtolower(...), $record);
// the following formatter will convert all the fields from your table to lowercase.

The following formatter will only work if the table has a header attached to it with a column named count.

$formatter = function (array $record): array {
   $record['count'] = (int) $record['count'];
   
   return $record;
}
// the following formatter will convert the data of all count column into integer..

ignoreXmlErrors and failOnXmlErrors

Tells whether the parser should ignore or throw in case of malformed HTML content.

use Bakame\HtmlTable\Parser;

$parser = (new Parser())->ignoreXmlErrors();   // ignore the XML errors
$parser = (new Parser())->failOnXmlErrors(3); // throw on XML errors

Testing

The library:

  • has a PHPUnit test suite
  • has a coding style compliance test suite using PHP CS Fixer.
  • has a code analysis compliance test suite using PHPStan.

To run the tests, run the following command from the project folder.

composer test

Security

If you discover any security related issues, please email nyamsprod@gmail.com instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

bakame/html-table 适用场景与选型建议

bakame/html-table 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 4.04k 次下载、GitHub Stars 达 11, 最近一次更新时间为 2023 年 09 月 23 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「import」 「filter」 「html」 「convert」 「export」 「transform」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 bakame/html-table 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 bakame/html-table 我们能提供哪些服务?
定制开发 / 二次开发

基于 bakame/html-table 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 4.04k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 11
  • 点击次数: 30
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 11
  • Watchers: 1
  • Forks: 2
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2023-09-23