Python ウェブページからテーブルを抽出

Salman Mehmood 2023年6月21日
  1. Python ウェブページからテーブルを抽出
  2. Pandasを使用してWebページからPython抽出テーブル
  3. lxml を使用して Web ページからテーブルを抽出する Python
Python ウェブページからテーブルを抽出

この記事の主な目的は、Python で Pandas と lxml を使用して Web ページからテーブルを抽出する方法を示すことです。

Python ウェブページからテーブルを抽出

多くの情報が毎日高頻度で処理、保存、抽出されるこの現代において、データは非常に重要です。 それに関して、私たちのプロジェクトでは、特定のオンラインの場所、リポジトリ、または Web ページからデータを抽出する必要がある場合があります。

これは、多くのユースケースで可能性があります。 おそらく、さまざまな理由でデータを抽出、処理、および保存するため、またはリポジトリからデータを抽出するために、公的記録保持サイトにアクセスする必要があります。

これを行うにはもっと良い方法がありますが、簡単にするために、これが必要な方法であると仮定しましょう。

この状況に対処するには、Web ページへの接続を確立し、ページ全体を読み取り、(存在する場合) テーブルを見つけ、それらを正しく抽出し、適切な形式で保存するソリューションを考案する必要があります。 これは、プログラムで処理できるようにするためです。

この問題の解決策には複数の方法がありますが、そのうちの 2つを以下に示します。

Pandasを使用してWebページからPython抽出テーブル

先に進む前に、次のモジュール/パッケージがインストールされていることを確認してください。

  1. lxml
  2. html5lib
  3. ビューティフルスープ4

上記のパッケージは、次のコマンドを使用して 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.ffiec.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 ライブラリを使用して、任意の Web ページからテーブルを簡単に抽出できます。 Pandas ライブラリの read_html メソッドを使用して、Web ページからデータを読み取って抽出し、それらをデータフレームに変換して、データが Dataframe オブジェクトになるため、データのスムーズな処理を支援できます。

抽出されたテーブルは、Dataframe オブジェクトを CSV ファイルに保存する to_csv メソッドを使用して CSV ファイルに保存することもできます。

lxml を使用して Web ページからテーブルを抽出する Python

次のコードを検討してください。

from lxml import etree
import urllib.request

site = "https://www.ffiec.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']
.
.
.
.
.

lxmlurllib を使用して Web ページからテーブルを抽出し、処理することもできます。 コードから明らかなように、リクエストにカスタム ヘッダーを提供する必要があります。 それ以外の場合、403: Forbidden エラーが発生します。

リクエストが成功すると、テーブルの検索が (特にこのサイトに対して) 実行され、その後、テーブルからヘッダーとコンテンツ (行) を手動で抽出します。

このオプションは Pandas モジュールよりも少し長くて複雑ですが、何を抽出し、何を抽出しないかに関して、より多くの制御と自由が必要な場合に役立ちます。

著者: Salman Mehmood
Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn