Python 从网页中提取表格
本文的主要目的是演示如何在 Python 中使用 Pandas 和 lxml 从网页中提取表格。
Python 从网页中提取表格
在这个现代时代,数据非常重要,每天都会以高频率处理、存储和提取大量信息。 就此而言,我们的项目可能要求我们从某个在线位置、存储库或网页中提取数据。
这在许多用例中都是可能的。 也许出于多种原因需要访问公共记录保存站点来提取、处理和存储数据,或者从我们的存储库中提取数据。
有更好的方法可以做到这一点,但为了简单起见,我们假设这是必需的方法。
为了解决这种情况,我们必须设计一个解决方案,建立与网页的连接,通读页面,找到任何表格(如果存在),正确提取它们,并以合适的格式存储它们。 这样它就可以在我们的程序中进行处理。
可以通过多种方式解决此问题,下面提到了其中两种:
Python 使用 Pandas 从网页中提取表格
在继续之前,请确保您安装了以下模块/包:
- lxml
- html5lib
- BeautifulSoup4
我们可以使用以下命令使用 pip 安装上述软件包:
pip install lxml html5lib BeautifulSoup4
这给出了以下输出:
Collecting lxml
Downloading lxml-4.9.1-cp310-cp310-win_amd64.whl (3.6 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.6/3.6 MB 37.9 kB/s eta 0:00:00
Requirement already satisfied: html5lib in c:\program files\python310\lib\site-packages (1.1)
Collecting BeautifulSoup4
Downloading beautifulsoup4-4.11.1-py3-none-any.whl (128 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 128.2/128.2 kB 29.0 kB/s eta 0:00:00
Requirement already satisfied: webencodings in c:\program files\python310\lib\site-packages (from html5lib) (0.5.1)
Requirement already satisfied: six>=1.9 in c:\program files\python310\lib\site-packages (from html5lib) (1.16.0)
Collecting soupsieve>1.2
Downloading soupsieve-2.3.2.post1-py3-none-any.whl (37 kB)
Collecting requests
Downloading requests-2.28.1-py3-none-any.whl (62 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 62.8/62.8 kB 420.8 kB/s eta 0:00:00
Collecting urllib3<1.27,>=1.21.1
Downloading urllib3-1.26.12-py2.py3-none-any.whl (140 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 140.4/140.4 kB 1.0 MB/s eta 0:00:00
Collecting idna<4,>=2.5
Downloading idna-3.4-py3-none-any.whl (61 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 61.5/61.5 kB 121.6 kB/s eta 0:00:00
Collecting charset-normalizer<3,>=2
Downloading charset_normalizer-2.1.1-py3-none-any.whl (39 kB)
Collecting certifi>=2017.4.17
Downloading certifi-2022.9.24-py3-none-any.whl (161 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 161.1/161.1 kB 1.4 MB/s eta 0:00:00
Installing collected packages: urllib3, idna, charset-normalizer, certifi, requests, soupsieve, lxml, BeautifulSoup4
Successfully installed BeautifulSoup4-4.11.1 lxml-4.9.1 soupsieve-2.3.2.post1 certifi-2022.9.24 charset-normalizer-2.1.1 idna-3.4 requests-2.28.1 urllib3-1.26.12
安装必要的模块后,就该进入实现部分了。
考虑以下代码:
import requests
import pandas as pd
url = 'https://www.test.gov/census/report.aspx?year=2020&county=009&state=09&report=demographic'
html = requests.get(url).content
df_list = pd.read_html(html)
df = df_list[-1]
print(df)
这给出了以下输出:
Tract Code Tract Income Level Distressed or Under-served Tract ... Minority Population Owner Occupied Units 1- to 4- Family Units
1 1202.0 Moderate No ... 3040 918 2010
2 1251.0 Middle No ... 551 1400 1555
3 1252.0 Moderate No ... 2088 1139 1992
4 1253.0 Moderate No ... 2443 728 1814
.. ... ... ... ... ... ... ...
95 1714.0 Moderate No ... 1278 141 638
96 1715.0 Moderate No ... 2241 396 1274
97 1716.0 Middle No ... 1466 1378 1803
98 1717.0 Middle No ... 820 1456 1647
99 1751.0 Middle No ... 851 669 1240
[100 rows x 12 columns]
使用 Pandas 库可以很容易地从任何网页中提取表格。 Pandas 库的 read_html 方法可用于从网页中读取和提取数据,然后将其转换为 DataFrame,以协助数据的顺利处理,因为它们成为 DataFrame 对象。
还可以使用 to_csv 方法将提取的表保存到 CSV 文件,该方法将 Dataframe 对象保存到 CSV 文件。
Python 使用 lxml 从网页中提取表格
考虑以下代码:
from lxml import etree
import urllib.request
site = "https://www.test.gov/census/report.aspx?year=2020&county=009&state=09&report=demographic"
hdr = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'Accept-Encoding': 'none',
'Accept-Language': 'en-US,en;q=0.8',
'Connection': 'keep-alive'}
request = urllib.request.Request(site, headers=hdr)
web = urllib.request.urlopen(request)
s = web.read()
html = etree.HTML(s)
## Get all 'tr'
tr_nodes = html.xpath('//table[@id="Report1_dgReportDemographic"]/tr')
## 'th' is inside first 'tr'
headers = [i.text for i in tr_nodes[0].xpath("th")]
## Get text from rest all 'tr'
td_content = [[td.text for td in tr.xpath('td')] for tr in tr_nodes[1:]]
for head in headers:
print(head, end=" ")
print("")
for content in td_content:
print(content)
这给出了以下输出:
Tract Code Tract Income Level Distressed or Under Tract Median Family Income % 2020 FFIEC Est. MSA/MD non-MSA/MD Median Family Income 2020 Est. Tract Median Family Income 2015 Tract Median Family Income Tract Population Tract Minority % Minority Population Owner Occupied Units 1- to 4- Family Units
['1201.00', 'Middle', 'No', '93.64', '$91,800', '$85,962', '$75,611', '6013', '26.44', '1590', '1862', '2248']
['1202.00', 'Moderate', 'No', '68.12', '$91,800', '$62,534', '$55,000', '6783', '44.82', '3040', '918', '2010']
['1251.00', 'Middle', 'No', '109.80', '$91,800', '$100,796', '$88,654', '4477', '12.31', '551', '1400', '1555']
['1252.00', 'Moderate', 'No', '62.55', '$91,800', '$57,421', '$50,506', '5912', '35.32', '2088', '1139', '1992']
['1253.00', 'Moderate', 'No', '57.28', '$91,800', '$52,583', '$46,250', '5164', '47.31', '2443', '728', '1814']
.
.
.
.
.
也可以使用 lxml 和 urllib 从网页中提取表格并进行处理。 从代码中可以明显看出,我们需要为请求提供自定义标头; 否则,收到 403: Forbidden 错误。
请求成功后,搜索表(专门针对该站点),然后我们手动从表中提取标题和内容(行)。
尽管此选项比 Pandas 模块更冗长和更复杂,但当需要更多控制和自由来决定要提取什么和不提取什么时,它很有用。
相关文章
Pandas DataFrame DataFrame.shift() 函数
发布时间:2024/04/24 浏览次数:133 分类:Python
-
DataFrame.shift() 函数是将 DataFrame 的索引按指定的周期数进行移位。
Python pandas.pivot_table() 函数
发布时间:2024/04/24 浏览次数:82 分类:Python
-
Python Pandas pivot_table()函数通过对数据进行汇总,避免了数据的重复。
Pandas read_csv()函数
发布时间:2024/04/24 浏览次数:254 分类:Python
-
Pandas read_csv()函数将指定的逗号分隔值(csv)文件读取到 DataFrame 中。
Pandas 多列合并
发布时间:2024/04/24 浏览次数:628 分类:Python
-
本教程介绍了如何在 Pandas 中使用 DataFrame.merge()方法合并两个 DataFrames。
Pandas loc vs iloc
发布时间:2024/04/24 浏览次数:837 分类:Python
-
本教程介绍了如何使用 Python 中的 loc 和 iloc 从 Pandas DataFrame 中过滤数据。
在 Python 中将 Pandas 系列的日期时间转换为字符串
发布时间:2024/04/24 浏览次数:894 分类:Python
-
了解如何在 Python 中将 Pandas 系列日期时间转换为字符串