簡體   English   中英

Python - 從復雜 HTML 中自動抓取表

[英]Python - Automatic table scraping from complex HTML

我正在嘗試自動將網站上每個表的所有數據和 output 每個表的所有數據抓取到 excel 中的選項卡中。

我一直在使用當前可用的代碼,例如https://www.thepythoncode.com/article/convert-html-tables-into-csv-files-in-pythonhttps://towardsdatascience.com/web -scraping-html-tables-with-python-c9baba21059 and Python - Web Scraping HTML table and printing to CSV .

使用此URL時,我很難同時提取基礎數據和表頭。 HTML 格式非常密集,因此我很難以正確的結構提取表。

我當前的代碼:

from bs4 import BeautifulSoup as bs
from urllib.request import urlopen
import re
import html2text
import requests
import pandas as pd

USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36"
# US english
LANGUAGE = "en-US,en;q=0.5"

def get_soup(url):
    """Constructs and returns a soup using the HTML content of `url` passed"""
    # initialize a session
    session = requests.Session()
    # set the User-Agent as a regular browser
    session.headers['User-Agent'] = USER_AGENT
    # request for english content (optional)
    session.headers['Accept-Language'] = LANGUAGE
    session.headers['Content-Language'] = LANGUAGE
    # make the request
    html = session.get(url)
    # return the soup
    return bs(html.content, "html.parser")

def get_all_tables(soup):
    """Extracts and returns all tables in a soup object"""
    return soup.find_all("table")

def get_table_headers(table):
    """Given a table soup, returns all the headers"""
    headers = []
    for th in table.find("tr").find_all("th"):
        headers.append(th.text.strip())
    return headers

def get_table_rows(table):
    """Given a table, returns all its rows"""
    rows = []
    for tr in table.find_all("tr")[1:]:
        cells = []
        # grab all td tags in this table row
        tds = tr.find_all("td")
        if len(tds) == 0:
            # if no td tags, search for th tags
            # can be found especially in wikipedia tables below the table
            ths = tr.find_all("th")
            for th in ths:
                cells.append(th.text.strip())
        else:
            # use regular td tags
            for td in tds:
                cells.append(td.text.strip())
        rows.append(cells)
    return rows

def save_as_csv(table_name, headers, rows):
    pd.DataFrame(rows, columns=headers).to_csv(f"{table_name}.csv")

def main(url):
    # get the soup
    soup = get_soup(url)
    # extract all the tables from the web page
    tables = get_all_tables(soup)
    print(f"[+] Found a total of {len(tables)} tables.")
    # iterate over all tables
    for i, table in enumerate(tables, start=1):
        # get the table headers
        headers = get_table_headers(table)
        # get all the rows of the table
        rows = get_table_rows(table)
        # save table as csv file
        table_name = f"table-{i}"
        print(f"[+] Saving {table_name}")
        save_as_csv(table_name, headers, rows)

main("https://www.sec.gov/Archives/edgar/data/1701605/000170160519000089/bkr-2019093010xq.htm")

例如,我需要代碼來識別一張表格,例如附圖中的表格,並將所有信息放入 excel 格式URL 中的表格

Code from questions such as Extract HTML Tables With Similar Data from Different Sources with Different Formatting - Python and Extract HTML Table Based on Specific Column Headers - Python is able to search through the URL, but is looking for too specific a criterion, as I need URL 中的所有表格。

任何幫助,將不勝感激! 我確定有一個我沒有看到的優雅解決方案

我看了看。 您帖子中的 URL 嚴重依賴 JavaScript 使用其元素填充頁面。 這就是為什么 BeautifulSoup 看不到它的原因。 模板 HTML 有十二個表,所有這些表最初看起來像這樣:

<table class="table table-striped table-sm">
    <tbody id="form-information-modal-carousel-page-1">
        <!-- Below is populated dynamically VIA JS -->
            <tr>
                <td class="text-center">
                    <i class="fas fa-spinner fa-spin"></i>
                </td>
            </tr>
    </tbody>
</table>
</div>
<div class="carousel-item table-responsive">
    <table class="table table-striped table-bordered table-sm">
        <tbody id="form-information-modal-carousel-page-2">
            <!-- Below is populated dynamically VIA JS -->
            ...

注意注釋<!-- Below is populated dynamically VIA JS --> 基本上所有有趣的數據都沒有包含在這個 HTML 中。 我記錄了我的網絡流量,頁面發出了兩個 XHR 請求。 一個看起來很有希望,即MetaLinks.json 它很大,但不幸的是表數據不在那里(仍然很感興趣,可能對其他事情有用)。 另一個 XHR 資源是包含烘焙表數據的實際 HTML 文檔。 JSON 會更好,因為我們不必使用 BeautifulSoup 來解析它,但無論如何。 順便說一句,這個 HTML 是我們真正要刮的那個。 我們不想抓取您提供的 URL(交互式內聯 XBRL 查看器)——它實際上使用 HTML XHR 資源來填充自身。 此 HTML 與單擊左上角的內聯 XBRL 查看器的漢堡菜單和 select“以 HTML 格式打開”時查看的相同。 如果您找不到它,URL 是: https://www.sec.gov/Archives/edgar/data/1701605/000170160519000089/bkr-2019093010xq.htm

編輯 - 這是一個小例子。 我只是從表格中提取一些數字:

def main():

    import requests
    from bs4 import BeautifulSoup

    url = "https://www.sec.gov/Archives/edgar/data/1701605/000170160519000089/bkr-2019093010xq.htm"

    response = requests.get(url, headers={})
    response.raise_for_status()

    soup = BeautifulSoup(response.content, "html.parser")

    for table in soup.find_all("table"):
        for row in table.find_all("tr"):
            for data in row.find_all("ix:nonfraction"):
                print(data.text, end=" ")
            print()
        print()


    return 0


if __name__ == "__main__":
    import sys
    sys.exit(main())

Output:

3,339 3,142 9,886 9,421 
2,543 2,523 7,604 7,191 
5,882 5,665 17,490 16,612 


2,901 2,819 8,647 8,371 
1,880 1,873 5,705 5,491 
679 608 2,083 1,944 
71 66 183 374 
54 17 128 113 
5,585 5,383 16,746 16,293 
297 282 744 319 
14 6 124 51 
59 55 174 164 
224 233 446 206 
— 85 — 139 
107 110 269 86 
117 38 177 19 
60 25 97 83 
57 13 80 64 
...

output 實際上比我展示的要長得多,但你明白了。 此外,我沒有從表格中提取所有相關數字,因為我只查看ix:nonfraction標簽,但還有其他類型(例如十進制數)。 HTML 非常密集 - 你必須弄清楚如何從每一行獲取所有其他字段,處理非ix:nonfraction標簽,處理空列等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM