如何从表中获取所有tr元素并单击链接?

时间:2018-08-22 15:39:17

标签: python python-3.x beautifulsoup

我试图弄清楚如何从表中打印所有tr元素,但是我不能完全正常工作。

这是我正在使用的链接。

https://en.wikipedia.org/wiki/List_of_current_members_of_the_United_States_Senate

这是我的代码。

insert_many

我正在尝试打印名为import requests from bs4 import BeautifulSoup link = "https://en.wikipedia.org/wiki/List_of_current_members_of_the_United_States_Senate" html = requests.get(link).text # If you do not want to use requests then you can use the following code below # with urllib (the snippet above). It should not cause any issue.""" soup = BeautifulSoup(html, "lxml") res = soup.findAll("span", {"class": "fn"}) for r in res: print("Name: " + r.find('a').text) table_body=soup.find('senators') rows = table_body.find_all('tr') for row in rows: cols=row.find_all('td') cols=[x.text.strip() for x in cols] print(cols) 的表中的所有tr元素。另外,我想知道是否有一种方法可以点击参议员的链接,例如'senators'可以带我到这里:

https://en.wikipedia.org/wiki/Richard_Shelby

我想从每个链接获取'Richard Shelby'下的数据。在这种情况下,值为:'Assumed office'。因此,最终,我想结束这一点:

'January 3, 2018'

我现在能得到的是打印出每个参议员的名字。

1 个答案:

答案 0 :(得分:1)

为了找到“ Senators”表,您可以先找到相应的“ Senators” label,然后再找到get the first following table element

soup.find(id='Senators').find_next("table")

现在,为了逐行获取数据,您将不得不考虑具有“行跨度”的单元格,这些单元格跨多行。您可以遵循What should I do when <tr> has rowspan中建议的方法,也可以遵循我在下面提供的实现方式(不理想,但可以使用)。

import copy

import requests
from bs4 import BeautifulSoup


link = "https://en.wikipedia.org/wiki/List_of_current_members_of_the_United_States_Senate"


with requests.Session() as session:
    html = session.get(link).text

    soup = BeautifulSoup(html, "lxml")
    senators_table = soup.find(id='Senators').find_next("table")

    headers = [td.get_text(strip=True) for td in senators_table.tr('th')]

    rows = senators_table.find_all('tr')

    # pre-process table to account for rowspan, TODO: extract into a function
    for row_index, tr in enumerate(rows):
        for cell_index, td in enumerate(tr('td')):
            if 'rowspan' in td.attrs:
                rowspan = int(td['rowspan'])

                del td.attrs['rowspan']

                # insert same td into subsequent rows
                for index in range(row_index + 1, row_index + rowspan):
                    try:
                        rows[index]('td')[cell_index].insert_after(copy.copy(td))
                    except IndexError:
                        continue

    # extracting the desired data
    rows = senators_table.find_all('tr')[1:]
    for row in rows:
        cells = [td.get_text(strip=True) for td in row('td')]
        print(dict(zip(headers, cells)))

然后,如果需要,请遵循指向参议员“个人资料”页面的链接,您首先需要将链接从适当的单元格中提取出来,然后使用session.get()“导航”到该链接,大致如下:

senator_link = row.find_all('td')[3].a['href']
senator_link = urljoin(link, senator_link)
response = session.get(senator_link)

soup = BeautifulSoup(response.content, "lxml")

# TODO: parse

其中urljoin的导入方式为:

from urllib.parse import urljoin

仅供参考,在这里使用requests.Session()的原因之一是优化向同一主机发出的请求:

  

Session对象允许您在请求中保留某些参数。它还会在来自会话实例的所有请求中保留cookie,并将使用urllib3的连接池。因此,如果您要向同一主机发出多个请求,则基础TCP连接将被重用,这可以显着提高性能


还有另一种获取表格数据的方法-pandas中的.read_html()。您可以这样做:

import pandas as pd

df = pd.read_html(str(senators_table))[0]
print(df.head())

获取所需的表作为数据框。