如何使用 Python 中的 BeautifulSoup 从 HTML link 解析嵌套的 table?

How to parse nested table from HTML link using BeautifulSoup in Python?

全部,

我正在尝试从这个 link http://web1.ncaa.org/stats/StatsSrv/careersearch 中解析 table。 请注意:要在 "School/Sport Search" select All for School, Year -2005-2006, Sport -Football, Division I 下搜索。我要解析的列是学校名称,如果您单击学校Name.More信息会输出。从那个 link/Table 我想为每一所学校解析 "Stadium Capacity"。我的问题是这样的事情可能吗?如果是,怎么办?我是 python 和 BeautifulSoup 的新手,如果你能提供解释那就太好了!

注:共有239条结果,

总结一下:所以基本上我想解析学校名称及其体育场容量并将其转换为 Pandas 数据框

import requests 
from bs4 import BeautifulSoup
URL = "http://web1.ncaa.org/stats/StatsSrv/careerteam"
r = requests.get(URL) 

soup = BeautifulSoup(r.content, 'html5lib') 
print(soup.prettify()) 

My question is Is something like this possible ?

是的。

If yes,how ?

下面的代码中有很多内容。但要点是弄清楚浏览器发出的 post 请求,然后使用 Requests 模拟它。我们可以通过检查工具中的“网络”选项卡找到正在发出的请求。

首先我们发出 'search' post 请求。这给出了左和右table。点击左边的 table 可以看到该地区的学校。但是如果我们仔细观察点击区域 link 也是一个 post 请求(我们必须使用 requests 来完成)

例如。单击 'Air Force - Eastern Ill.' 会给我们一个 table,其中包含该地区的 link 所学校。那我们得去那所学校link算一下容量。

因为点击每个学校 link 也是一个 post 请求,我们必须模拟这个 returns 学校页面。我们从这里抓取学校名称和容量。

您可以阅读 Advanced Usage of requests to know about Session objects, Making a request 了解如何使用 Requests 提出请求。

import requests
from bs4 import BeautifulSoup
import pandas as pd
end_list=[]
s = requests.Session()
URL = "http://web1.ncaa.org/stats/StatsSrv/careersearch"
data={'doWhat': 'teamSearch','searchOrg': 'X', 'academicYear': 2006, 'searchSport':'MFB','searchDiv': 1}
r = s.post(URL,data=data)
soup=BeautifulSoup(r.text,'html.parser')
area_list=soup.find_all('table')[8].find_all('tr')
area_count=len(area_list)#has no of areas + 1  tr 'Total Results of Search:  239'
for idx in range(0,area_count):
    data={
    'sortOn': 0,
    'doWhat': 'showIdx',
    'playerId':'' ,'coachId': '',
    'orgId':'' ,
    'academicYear':'' ,
    'division':'' ,
    'sportCode':'' ,
    'idx': idx
    }
    r = s.post(URL,data=data)
    soup=BeautifulSoup(r.text,'html.parser')
    last_table=soup.find_all('table')[-1]#last table
    for tr in last_table.find_all('tr'):
        link_td=tr.find('td',class_="text")
        try:
            link_a=link_td.find('a')['href']
            data_params=link_a.split('(')[1][:-2].split(',')
            try:
                #print(data_params)
                sports_code=data_params[2].replace("'","").strip()
                division=int(data_params[3])
                player_coach_id=int(data_params[0])
                academic_year=int(data_params[1])
                org_id=int(data_params[4])
                #print(sports_code,division,player_coach_id,academic_year,org_id)
                data={
                'sortOn': 0,
                'doWhat': 'display',
                'playerId': player_coach_id,
                'coachId': player_coach_id,
                'orgId': org_id,
                'academicYear': academic_year,
                'division':division,
                'sportCode':sports_code,
                'idx':''
                }
                url='http://web1.ncaa.org/stats/StatsSrv/careerteam'
                r = s.post(url,data=data)
                soup2=BeautifulSoup(r.text,'html.parser')
                institution_name=soup2.find_all('table')[1].find_all('tr')[2].find_all('td')[1].text.strip()
                capacity=soup2.find_all('table')[4].find_all('tr')[2].find_all('td')[1].text.strip()
                #print([institution_name, capacity])
                end_list.append([institution_name, capacity])

            except IndexError:
                pass

        except AttributeError:
            pass
#print(end_list)
headers=['School','Capacity']
df=pd.DataFrame(end_list, columns=headers)
print(df)

输出

                School Capacity
0            Air Force   46,692
1                Akron   30,000
2              Alabama  101,821
3         Alabama A&M;   21,000
4          Alabama St.   26,500
5          Albany (NY)    8,500
6               Alcorn   22,500
7      Appalachian St.   30,000
8              Arizona   55,675
9          Arizona St.   64,248
10     Ark.-Pine Bluff   14,500
11            Arkansas   72,000
12        Arkansas St.   30,708
13     Army West Point   38,000
14              Auburn   87,451
15         Austin Peay   10,000
16                 BYU   63,470
17            Ball St.   22,500
18              Baylor   45,140
19     Bethune-Cookman    9,601
20           Boise St.   36,387
21      Boston College   44,500
22       Bowling Green   24,000
23               Brown   20,000
24            Bucknell   13,100
25             Buffalo   29,013
26              Butler    5,647
27            Cal Poly   11,075
28          California   62,467
29   Central Conn. St.    5,500
..                 ...      ...
209               UCLA   91,136
210              UConn   40,000
211                UNI   16,324
212               UNLV   36,800
213          UT Martin    7,500
214               UTEP   52,000
215               Utah   45,807
216           Utah St.   25,100
217                VMI   10,000
218         Valparaiso    5,000
219         Vanderbilt   40,350
220          Villanova   12,000
221           Virginia   61,500
222      Virginia Tech   65,632
223             Wagner    3,300
224        Wake Forest   31,500
225         Washington   70,138
226     Washington St.   32,740
227          Weber St.   17,500
228      West Virginia   60,000
229      Western Caro.   13,742
230       Western Ill.   16,368
231        Western Ky.   22,113
232      Western Mich.   30,200
233     William & Mary   12,400
234          Wisconsin   80,321
235            Wofford   13,000
236            Wyoming   29,181
237               Yale   64,269
238     Youngstown St.   20,630

[239 rows x 2 columns]

注意: 这将需要很长时间。我们正在 抓取 >239 页。所以请耐心等待。可能需要 15 分钟或更长时间。