首页 > 解决方案 > 如何从使用 bs4 收集的表中提取索引信息?(Python)

问题描述

我正在尝试从nysenate.gov上抓取立法信息。我在 Jupyter Notebook 中使用 bs4 和 Python。有一个表格可能/可能不包含以下信息:

  1. 提交给州长的法案(和日期)
  2. 由政府签署的法案(和日期)
  3. 被政府否决的法案(和日期)

我可以毫无问题地收集 #1。但数字 2 和 3 不断分崩离析。我怀疑这是因为有额外的自动生成的特定于账单的文本不断炸毁我的刮板。我尝试使用正则表达式来解决这个问题。这是我尝试过的:

    tablebody=soup.select_one(".table.c-bill--actions-table > tbody")
                
    check_list = [item.text.strip() for item in tablebody.select("td")]
    
    #print(check_list)

    if "delivered to governor" in check_list:
        transfer_list.append("delivered to governor")
        i = check_list.index("delivered to governor")
        transfer_list.append(check_list[i+1])

    else:
        transfer_list.append("not delivered")
        transfer_list.append("no date")

    if regex_for_signed in check_list:
        transfer_list.append("signed")
        i = check_list.index("signed")
        transfer_list.append(check_list[i+1])

    else:
        transfer_list.append("not signed")
        transfer_list.append("no date")

    if regex_for_vetoed in check_list or "tabledvetoed" in check_list:
        transfer_list.append("vetoed")
        i = check_list.index("vetoed")
        transfer_list.append(check_list[i+1])

    else:
        transfer_list.append("not vetoed")
        transfer_list.append("no date")

这是我正在使用的正则表达式:

regex_for_signed = r"((?i)signed).*"
regex_for_vetoed = r"((?i)vetoed).*"

这是我用来测试代码的两个网页:

https://www.nysenate.gov/legislation/bills/2019/s5903(已签名) https://www.nysenate.gov/legislation/bills/2019/s5918(否决)

我正在尝试将output其转换为 CSV 文件。对于signedandvetoed场景,它总是使用else语句——即使它不应该使用。

标签: pythonbeautifulsoup

解决方案


以下是将结果写入多个 URL 的 CSV 文件的一种可能方法:

from bs4 import BeautifulSoup
import requests
import csv

urls = [
    "https://www.nysenate.gov/legislation/bills/2019/s5903",
    'https://www.nysenate.gov/legislation/bills/2019/s5918',
]

with open('output.csv', 'w', newline='') as f_output:
    csv_output = csv.writer(f_output)
    csv_output.writerow(['Date', 'Status', 'Text'])
    
    for url in urls:
        r = requests.get(url)
        soup = BeautifulSoup(r.content, 'lxml')
        table_body = soup.select_one(".table.c-bill--actions-table > tbody")

        for tr in table_body.find_all('tr'):
            entry_date, entry_text = [td.get_text(strip=True) for td in tr.find_all('td')]
            status = ""
        
            if "delivered to governor" in entry_text:
                status = "delivered to governor"
            elif "signed" in entry_text:
                status = "signed"
            
            csv_output.writerow([entry_date, status, entry_text])

对于正则表达式,您将需要使用re.search()


推荐阅读