使用 Beautiful Soup 从表中提取日期

时间:2021-04-07 13:35:18

标签: python regex web-scraping beautifulsoup

我希望对已交付给州长的法案做一些事情 - 收集交付日期和发送前最后一次立法行动的日期。

我正在为一系列类似的 URL 执行此操作。问题是,我的代码(如下)适用于某些 URL 而不是其他 URL。我正在将其写入熊猫数据框,然后写入 csv 文件。当代码失败时,它会在应该触发 elseif 时写入 elif 块。

这是一个失败的 URL:https://www.nysenate.gov/legislation/bills/2011/s663 还有一个成功的网址:https://www.nysenate.gov/legislation/bills/2011/s333

以第一个 URL 为例。在“查看操作”下拉菜单下方,它说它于 2011 年 7 月 29 日交付给州长。在此之前,它于 2011 年 6 月 20 日返回组装。

使用“交付给州长”位置作为表中的 td,我想使用 Bs4 收集两个日期。

这是我的代码中的内容:

check_list = [item.text.strip() for item in tablebody.select("td")]

dtg = "delivered to governor"
dtg_regex = re.compile(
    '/.*(\S\S\S\S\S\S\S\S\S\s\S\S\s\S\S\S\S\S\S\S\S).*'
)
        
if dtg in check_list:

    i = check_list.index(dtg)
    transfer_list.append(check_list[i+1]) ## last legislative action date (not counting dtg)
    transfer_list.append(check_list[i-1]) ## dtg date
            
elif any(dtg_regex.match(dtg_check_list) for dtg_check_list in check_list):
    transfer_list.append(check_list[4])
    transfer_list.append(check_list[2])
            
else:
    transfer_list.append("no floor vote")
    transfer_list.append("not delivered to governor")

2 个答案:

答案 0 :(得分:1)

您可以使用 :has 和 :contains 来定位正确的第一行,并使用 find_next 移动到下一行。您可以使用 last-of-type 获取第一行中的最后一个操作 select_one 以获取第二行中的第一个。您可以使用每个“列”的类在第一列和第二列之间移动。

您的里程可能因其他页面而异。

import requests
from bs4 import BeautifulSoup as bs

links = ['https://www.nysenate.gov/legislation/bills/2011/s663', 'https://www.nysenate.gov/legislation/bills/2011/s333']
transfer_list = []

with requests.Session() as s:
    for link in links:
        r = s.get(link)
        soup = bs(r.content, 'lxml')
        target = soup.select_one('.cbill--actions-table--row:has(td:contains("delivered"))')
        
        if target:
            print(target.select_one('.c-bill--actions-table-col1').text)
            # transfer_list.append(target.select_one('.c-bill--actions-table-col1').text)   
            print(target.select_one('.c-bill--action-line-assembly:last-of-type, .c-bill--action-line-senate:last-of-type').text)
            # transfer_list.append(target.select_one('.c-bill--action-line-assembly:last-of-type, .c-bill--action-line-senate:last-of-type').text)
            print(target.find_next('tr').select_one('.c-bill--actions-table-col1').text)
            # append again
            print(target.find_next('tr').select_one('.c-bill--actions-table-col2 span').text)
            # append again
        else:
            transfer_list.append("no floor vote")
            transfer_list.append("not delivered to governor")

答案 1 :(得分:0)

充分利用 XPath:


获取“交付给州长”的日期

//text()[contains(lower-case(.), 'delivered to governor')]/ancestor::tr/td[1]/text()

S663A - http://xpather.com/bUQ6Gva8

S333 - http://xpather.com/oTNfuH75


获取“返回议会/参议院”的日期

//text()[contains(lower-case(.), 'delivered to governor')]/ancestor::tr/following-sibling::tr/td//text()[contains(lower-case(.), 'returned to')]/ancestor::tr/td[1]/text()

S663A - http://xpather.com/Rnufm2TB

S333 - http://xpather.com/4x9UHn4L


获取在“交付给州长”行之前的行动日期,无论行动是什么

//text()[contains(lower-case(.), 'delivered to governor')]/ancestor::tr/following-sibling::tr[1]/td/text()

S663A - http://xpather.com/AUpWCFIz

S333 - http://xpather.com/u8LOCb0x