整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

如何使用Pandas read_html从HTML表格中获取数据

本Pandas教程中,我们将详细介绍如何使用Pandas read_html方法从HTML中获取数据。首先,在最简单的示例中,我们将使用Pandas从一个字符串读取HTML。其次,我们将通过几个示例来使用Pandas read_html从Wikipedia表格中获取数据。在之前的一篇文章(关于Python中的探索性数据分析)中,我们也使用了Pandas从HTML表格中读取数据。

在Python中导入数据

在开始学习Python和Pandas时,为了进行数据分析和可视化,我们通常从实践导入数据开始。在之前的文章中,我们已经了解到我们可以直接在Python中输入值(例如,从Python字典创建Pandas dataframe)。然而,通过从可用的源导入数据来获取数据当然更为常见。这通常是通过从CSV文件或Excel文件中读取数据来完成的。例如,要从一个.csv文件导入数据,我们可以使用Pandas read_csv方法。这里有一个如何使用该方法的快速的例子,但一定要查看有关该主题的博客文章以获得更多信息。

现在,上面的方法只有在我们已经有了合适格式的数据(如csv或JSON)时才有用(请参阅关于如何使用Python和Pandas解析JSON文件的文章)。

我们大多数人会使用Wikipedia来了解我们感兴趣的主题信息。此外,这些Wikipedia文章通常包含HTML表格。

要使用pandas在Python中获得这些表格,我们可以将其剪切并粘贴到一个电子表单中,然后,例如使用read_excel将它们读入Python。现在,这个任务当然可以用更少的步骤来完成:我们可以通过web抓取来对它进行自动化。一定要查看一下什么是web抓取。

先决条件

当然,这个Pandas读取HTML教程将要求我们安装Pandas及其依赖项。例如,我们可以使用pip来安装Python包,比如Pandas,或者安装一个Python发行版(例如,Anaconda、ActivePython)。下面是如何使用pip安装Pandas: pip install pandas。

注意,如果出现消息说有一个更新版本的pip可用,请查看这篇有关如何升级pip的文章。注意,我们还需要安装lxml或BeautifulSoup4,当然,这些包也可以使用pip来安装: pip install lxml。

Pandas read_html 语法

下面是如何使用Pandas read_html从HTML表格中抓取数据的最简单的语法:

现在我们已经知道了使用Pandas读取HTML表格的简单语法,接下来我们可以查看一些read_html示例。

Pandas read_html 示例1:

第一个示例是关于如何使用Pandas read_html方法的,我们将从一个字符串读取HTML表格。

现在,我们得到的结果不是一个Pandas DataFrame,而是一个Python列表。也就是说,如果我们使用type函数,我们可以看到:

如果我们想得到该表格,我们可以使用列表的第一个索引(0)

Pandas read_html 示例 2:

在第二个Pandas read_html示例中,我们将从Wikipedia抓取数据。实际上,我们将得到蟒科蛇(也称为蟒蛇)的HTML表格。

现在,我们得到了一个包含7个表(len(df))的列表。如果我们去Wikipedia页面,我们可以看到第一个表是右边的那个。然而,在本例中,我们可能对第二个表更感兴趣。

Pandas read_html 示例 3:

在第三个示例中,我们将从瑞典的covid-19病例中读取HTML表。这里,我们将使用read_html方法的一些附加参数。具体来说,我们将使用match参数。在此之后,我们还需要清洗数据,最后,我们将进行一些简单的数据可视化操作。

使用Pandas read_html和匹配参数抓取数据:

如上图所示,该表格的标题为:“瑞典各郡新增COVID-19病例”。现在,我们可以使用match参数并将其作为一个字符串输入:

通过这种方式,我们只得到这个表,但它仍然是一个dataframes列表。现在,如上图所示,在底部,我们有三个需要删除的行。因此,我们要删除最后三行。

使用Pandas iloc删除最后的行

现在,我们将使用Pandas iloc删除最后3行。注意,我们使用-3作为第二个参数(请确保你查看了这个Panda iloc教程,以获得更多信息)。最后,我们还创建了这个dataframe的一个副本。

在下一节中,我们将学习如何将多索引列名更改为单个索引。

将多索引更改为单个索引并删除不需要的字符

现在,我们要去掉多索引列。也就是说,我们将把2列索引(名称)变成唯一的列名。这里,我们将使用DataFrame.columns 和 DataFrame.columns,get_level_values:

最后,正如你在“date”列中所看到的,我们使用Pandas read_html从WikiPedia表格抓取了一些注释。接下来,我们将使用str.replace方法和一个正则表达式来删除它们:

使用Pandas set_index更改索引

现在,我们继续使用Pandas set_index将日期列变成索引。这样一来,我们稍后就可以很容易地创建一个时间序列图。

现在,为了能够绘制这个时间序列图,我们需要用0填充缺失的值,并将这些列的数据类型更改为numeric。这里我们也使用了apply方法。最后,我们使用cumsum方法来获得列中每个新值累加后的值:

来自HTML表格的时间序列图

在最后一个示例中,我们使用Pandas read_html获取我们抓取的数据,并创建了一个时间序列图。现在,我们还导入了matplotlib,这样我们就可以改变Pandas图例的标题的位置:

结论: 如何将HTML读取到一个 Pandas DataFrame

在这个Pandas教程中,我们学习了如何使用Pandas read_html方法从HTML中抓取数据。此外,我们使用来自一篇Wikipedia文章的数据来创建了一个时间序列图。最后,我们也可以通过参数index_col来使用Pandas read_html将' Date '列设置为索引列。

英文原文:https://www.marsja.se/how-to-use-pandas-read_html-to-scrape-data-from-html-tables
译者:一瞬

、在线表格编辑器——TablesGenerator

表格制作工具TablesGenerator是一个在线制作 LaTeX、HTML、Markdown 格式的表格代码工具,支持在表格中填充数据,修改字体/背景颜色,对齐方式等等,还支持从 Excel、Google Docs 里直接复制粘贴数据,以及多个 HTML 表格样式。Tables Generator 支持四种格式:LaTeX、HTML、Markdown、TEXT,先在 Table > Set size 中设置表格大小,然后填充数据,设置格式,就能在页面下面找到代码了。




2、在线表格编辑器——思迈特软件Smartbi


其以“真Excel”操作的特色,拥有了其它报表软件望尘莫及的功能特色。只要在Excel端安装Smartbi报表工具插件,用户就可以直接在Excel中设计报表格式或进行数据分析。Smartbi表格制作工具巧妙利用Excel自身的表格、图形、函数的能力,就能够实现各种BI应用,还可将报表一键发布到Web/APP端进行浏览,且软件内置多种免费的表格模板可供使用。

针对类似模板固定的Word/PPT分析报告,Smartbi利用Office分析报告插件,将报告模板中的数据元素数据(单数字、表格、图形)从“静态”变成“动态”,每当需要使用时,数据分析师可以像刷新报表一样刷新这些分析报告,按照所输入的参数对报告数据进行解读、讨论、建议,从而将更多时间用在“分析”上。



3、在线表格编辑器——FCKeditor 编辑器


FCKeditor 是一款开源的所见所得网页文本编辑器,可通过CKeditor设置表格,在表格中定义表单元素,主要支持文本框、复选框、单选框、单行文本、多行文本、列表、按钮、图片、隐藏域。




4、在线表格编辑器——Ueditor Formdesign Plugins Web表单设计器


Ueditor Formdesign 是开源免费的表单设计器,可应用于工作流管理系统、OA等,是一款可视化的Web表单构建器,HTML元素组件较丰富,主要包含:文本框、多行文本、下拉菜单、单选框、复选框、宏控件、进度条等,并可以生成二维码。




5、在线表格编辑器——SpreadJS


SpreadJS 在线Excel表格编辑器,是类似在线Excel功能和外观的在线表格编辑程序,也是 SpreadJS 桌面设计器的在线版本,提供源代码,可自由定制,任意扩展。该产品内嵌了SpreadJS,使用离线和在线方式均可进行表格编辑。

. 前言

在上一篇中,我故意留下了查询的示范没讲。虽然说可以通过以下代码获取一个DataReader:

IDataReader reader = command.ExecuteReader();

然后通过reader一行一行的读取数据,但是我并不推荐这样使用。

在查询这一高频需求上,C#为之做了很多工作,提供了更多的选择。这里介绍一个查询的另一套写法。



1. 离线查询

C#在查询上提供了另一种机制,可以一次性从数据库把结果读取到网络缓存区中,直到使用的时候才加载到程序中。

在离线查询里最关键的三个接口或类:

  • IDataAdapter 一种适配器,用来获取数据并填充或更新DataSet
  • DataSet 表示数据在内存中的缓存
  • DataTable 表示内存中一个数据表

IDataAdapter用来提供数据,DataSet表示adapter读取的结果集,其中有一个DataTable集合表示执行的SQL查询结果。至于为什么是集合,是因为IDataAdapter允许运行多条查询语句。

好,让我们粗略浏览一下这个三个关键点的属性和方法:

IDataAdapter:

public int Fill (System.Data.DataSet dataSet);//将查询出来的结果填充到DataSet里

在C#内部,其实不允许推荐直接继承该接口,推荐继承DataAdapter类,该类规定了数据库Adapter在初始化的时候,必须提供一个可以访问的数据库连接和要执行的命令文本。

当然其部分实现类允许以属性的形式后赋值这两个关键内容。

DataSet:

public DataSet ();
public DataSet (string dataSetName);//指定数据集的名称
public System.Data.DataTableCollection Tables { get; }//获取包含在 DataSet 中的表的集合

DataSet有很多有用的方法,但是在今天我们只用关系这些就可以了。

其中Tables 引入了一个没有提到的类型,DataTableCollection。那么我们可以顺藤摸瓜,来看看里面有什么关键的内容:

public System.Data.DataTable this[int index] { get; }// 获取指定下标的DataTable
public System.Data.DataTable this[string name] { get; }//获取具有指定名称的DataTable

可以看到提供了一种我们可以获取到里面的DataTable元素的索引访问方式。

DataTable :

public System.Data.DataSet DataSet { get; }//获取此表所属的 DataSet。
public System.Data.DataColumnCollection Columns { get; }//获取属于该表的列的集合
public System.Data.DataRowCollection Rows { get; }//获取属于该表的行的集合

又出现了两个新的类:DataColumnCollection、DataRowCollection。这是一种内部集合的实现类,功能类似于List,但又不等同于List。

我们大概看一下对我们有用的属性和方法:

DataColumnCollection:

public virtual int Count { get; }//获取集合中的元素总数
public System.Data.DataColumn this[int index] { get; }//从集合中获取位于指定索引位置的 DataColumn
public System.Data.DataColumn this[string name] { get; }//从具有指定名称的集合中获取 DataColumn。

DataRowCollection:

public override int Count { get; }
public System.Data.DataRow this[int index] { get; }// 获取索引处的行

嗯,好先到此为止。调转方向回到上个路口,重新来。让我们看看DataColumn和DataRow又有哪些值得我们现在关注的:

DataColumn:

public string ColumnName { get; set; }//获取或设置 DataColumnCollection 中的列的名称
public Type DataType { get; set; }//获取或设置存储在列中的数据的类型

DataRow:

public object this[System.Data.DataColumn column] { get; set; }//获取或设置指定 DataColumn 中存储的数据
public object this[int columnIndex] { get; set; }//获取或设置由索引指定的列中存储的数据
public object this[string columnName] { get; set; }//获取或设置由名称指定的列中存储的数据
public object[] ItemArray { get; set; }//通过数组获取或设置此行的所有值

到目前为止,离线查询的支持类和接口就介绍了个大概。那么我们看看如何进行一个离线查询吧



2.实践看看

以SQL Server数据库为例:

获取一个SqlDataAdapter,C#提供了四种方式获取:

public SqlDataAdapter ();//构造一个没有连接和命令的Adapter对象
public SqlDataAdapter (System.Data.SqlClient.SqlCommand selectCommand);// 指定一个查询命令
public SqlDataAdapter (string selectCommandText, System.Data.SqlClient.SqlConnection selectConnection);//指定查询命令,和连接
public SqlDataAdapter (string selectCommandText, string selectConnectionString);//指定查询命令和连接字符串

引用命名空间:

using System.Data;
using System.Data.SqlClient;

那么,我们先构造一个Adapter:

var connectStr = "Data Source=.;Initial Catalog=Old;Integrated Security=True";
var sql = "select * from Area_PostCode";
var adapter = new SqlDataAdapter(sql, connectStr);

然后创建一个用于保存数据的DataSet,并把数据填充进去:

DataSet set = new DataSet();
adapter.Fill(set);

然后可以看到这个set中的数据应该是这样的:

上图是在VS中的调试模式中,可以看到

根据上图我们大概可以猜测一下DataTable内部的数据结构,或者C#让我们理解的结构是什么。

其中DataColumn对应着图中列,ColumnName就是图 所示的列名。而DataRow就是行,ItemArray则是一行行数据。

这样一来,显然就比直接使用IDataReader访问数据要方便很多。

依据上例:

我们试着获取一下第三行的Province列值,如果觉得这个表述别扭的话,看一下我的写法,就知道我为什么这么表示了。

var table = set.Tables[0];// 先拿到第一个表
var value = table.Rows[2]["Province"];

这是一种蚂蚁搬家式的读取数据方式。C#为DataTable提供了一个扩展方法:

public static EnumerableRowCollection<DataRow> AsEnumerable(this DataTable source);

将表格转换成可枚举的DataRow集合。

所以我们可以用foreach循环来遍历DataTable。



3. 未完待续

在这一节简单介绍了一下ADO.NET的离线查询支持。当我们能从数据库中获取到DataTable的时候,我们就能通过这个做出更多的事情来。下一章我将带领大家结合之前介绍的反射,实现一个简单的ORM工具类。

更多内容烦请关注我的博客《高先生小屋》