在Python中用漂亮的汤循环遍历html

时间:2019-01-11 23:41:20

标签: python beautifulsoup

我正在尝试遍历html表。

我正在浏览的页面上只有一张桌子。这样很容易找到。在此之下,有几个<tr>,而我想通过<th>而不是<td>定义的某些标头来浏览这些标题。每个<tr><td>中的几个不同的类别组成。我只想收集class =“ table-name”的两个<td>和class =“ table-score”的<td>

我尝试与之合作:

rows = html.find("table", class_="table").find_all("tr")

for row in rows:
    if row.find("th") is None:
        td_names = row.findall("td")

for td_name in td_names:
    print(td_name)

但是我真的取得了成功。

因此,基本上html看起来像这样:

<table>
  <tr>
    <th>Header</th>
  </tr>
  <tr>
    <td class="table-rank">1</td>
    <td class="table-name">John</td>
    <td class="table-name">Jim</td>
    <td class="table-place">Russia</td>
    <td class="table-score">2-1</td>
  </tr>
</table>

我只在寻找“约翰”,“吉姆”,“ 2-1”。

谢谢。

3 个答案:

答案 0 :(得分:1)

find_all()将返回与过滤器匹配的所有元素的列表。您可以使用列表的索引来选择所需的元素。第一个为0,第二个为1,等等。

from bs4 import BeautifulSoup
html="""
<table>
<tr>
<th>Header</th>
</tr>
<tr>
<td class="table-rank">1</td>
<td class="table-name">John</td>
<td class="table-name">Jim</td>
<td class="table-place">Russia</td>
<td class="table-score">2-1</td>
</tr>
</table>
"""
soup=BeautifulSoup(html,'html.parser')
our_tr=soup.find('table').find_all('tr')[1] #the second tr in the table - index starts at 0
#print all td's of seconf tr
our_tds=our_tr.find_all('td')
print(our_tds[1].text)
print(our_tds[2].text)
print(our_tds[4].text)

输出

John
Jim
2-1

答案 1 :(得分:-1)

在您的特定示例中,$router将不返回任何内容,因为它正在查找类名称为“ table”的表。您在这里的.find("table", class_="table")标签只是<table>,而不是<table>

我做了以下工作,并且能够提取所需类的项目。

<table class="table">

我将from bs4 import BeautifulSoup html = """ <table> <tr> <th>Header</th> </tr> <tr> <td class="table-rank">1</td> <td class="table-name">John</td> <td class="table-name">Jim</td> <td class="table-place">Russia</td> <td class="table-score">2-1</td> </tr> </table> """ soup = BeautifulSoup(html, 'html.parser') t = soup.find('table') td_data = [] for row in t.find_all('tr'): # Ignore any rows containing a <th> cell. if not row.th: # Generate a list of any strings found inside <td class="table-name"> tags. # Concatenate this list with td_data. Do the same with cells of the class "table-score". td_data += [ s.string for s in row.find_all('td', class_="table-name") ] td_data += [ s.string for s in row.find_all('td', class_="table-score") ] print(td_data) 声明为一个空列表,然后将新列表添加到其中的原因是,这样您就可以对表中有多个行的表运行该算法,这些行可能具有您要查找的内容。另外,您可以通过某些方式对所需的任何一个类进行“或”搜索以找到标记,但是由于只有两个类,因此我认为收集表的完整列表非常简单,名称值和表得分值。如果其中之一为空,则td_data不变。

答案 2 :(得分:-1)

如果我看到table标签,我通常会让熊猫来做,您可以过滤掉不需要或不需要的列。

html = """
<table>
  <tr>
    <th>Header</th>
  </tr>
  <tr>
    <td class="table-rank">1</td>
    <td class="table-name">John</td>
    <td class="table-name">Jim</td>
    <td class="table-place">Russia</td>
    <td class="table-score">2-1</td>
  </tr>
</table>
"""

import pandas as pd


df = pd.read_html(html, skiprows=1)
results = df[0]

编辑: 但是,如果您更关心实际的类属性,我可以提供两种选择。

选项:1

仍然使用熊猫解析表,但在此之前,请使用BeautifulSoup通过.decompose()消除不需要的列/标签/类(无论您要调用什么):

import pandas as pd
import bs4

html = """
<table>
  <tr>
    <th>Header</th>
  </tr>
  <tr>
    <td class="table-rank">1</td>
    <td class="table-name">John</td>
    <td class="table-name">Jim</td>
    <td class="table-place">Russia</td>
    <td class="table-score">2-1</td>
  </tr>
</table>
"""

soup = bs4.BeautifulSoup(html, 'html.parser')

keep_list = ["table-name", "table-score"]

for data in soup.find_all('td'):
    class_attr = data['class'][0]
    if class_attr in keep_list:
        continue
    else:
        soup.select("td."+class_attr)[0].decompose()

df = pd.read_html(str(soup), skiprows=1)
results = df[0]

输出:

print (results)
      0    1    2
0  John  Jim  2-1

选项:2

与其他解决方案类似,只需找到特定的类属性即可。

import bs4

html = """
<table>
  <tr>
    <th>Header</th>
  </tr>
  <tr>
    <td class="table-rank">1</td>
    <td class="table-name">John</td>
    <td class="table-name">Jim</td>
    <td class="table-place">Russia</td>
    <td class="table-score">2-1</td>
  </tr>
</table>
"""

soup = bs4.BeautifulSoup(html, 'html.parser')

keep_list = ["table-name", "table-score"]
alpha = soup.find_all('td', class_=lambda x: x in keep_list)

for data in alpha:
    print (data.text)

# or if wanted in list
results = [ data.text for data in alpha ]

输出:

John
Jim
2-1

或者,列表可以分为3行:

soup = bs4.BeautifulSoup(html, 'html.parser')

keep_list = ["table-name", "table-score"]

results = [ data.text for data in soup.find_all('td', class_=lambda x: x in keep_list)]

输出:

print (results)
['John', 'Jim', '2-1']