Python BeautifulSoup 自动跟踪内容表格的行和列

1 投票
2 回答
2611 浏览
提问于 2025-04-16 15:08

首先让我说,我是新来的,对Stack和Python都不太熟悉。上周才开始接触它。不过,我在PHP、C++、Pascal、ADA、B和Forth方面有不少经验(这显示了我的年龄)。

我写了一个脚本,从一个网站上提取产品页面,并把它们存储在本地的MySQL数据库里。这样做是为了在晚上网站负载较轻的时候进行抓取。现在我需要从每个页面的HTML中提取产品描述。这些描述是放在表格里的。不过,每个页面的相关信息可能在不同的行和列中。

我可以确定的几点是:

  • 每个表格都有一个标题,说明下面行和列的数据。
  • 标题的文字是固定的,比如“Part”总是指零件类型,而“Part No.”总是指零件编号。
  • 并不是所有页面都会包含所有想要的数据。如果找不到某些数据,就只能保存找到的内容。

下面的部分是我遇到问题的地方,如何从一行中选择第n列?

我现在的做法是:

获取所需的列

  • 从数据库中获取HTML文档
  • 抓取表格(我的表格总是位于页面唯一的div中)
  • 抓取所有行(其实只需要处理第一行)
  • 对于每一行,当我找到想要的字段名称时,记录下行和列的索引。

获取数据值

  • 对于每一行:
  • 如果是标题行就跳过(记录下包含标题字段的行数)
  • 对于每一列,抓取文本值。
  • 把这些值保存到数据库中。

我页面中重要的部分看起来是这样的:

<div>
   ... 
   <table>
      <tr><td>&nbsp;</td><td><b>Item</b></td><td>&nbsp;</td><td><b>Description</b></td><td>&nbsp;</td><td><b>Part No.</b></td><td>&nbsp;</td><td><b>Color</b></td><td>&nbsp;</td></tr>
      <tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>
      <tr><td>&nbsp;</td><td>Toaster</td><td>&nbsp;</td><td>2-Slice</td><td>&nbsp;</td><td>#25713</td><td>&nbsp;</td><td>Chorme</td><td>&nbsp;</td></tr>
   </table>
   ...
</div>

非常感谢任何回复的人。

2 个回答

0

这是我处理这个问题的方法:

from BeautifulSoup import BeautifulSoup

doc = '''<div>
   <table>
      <tr><td>&nbsp;</td><td><b>Item</b></td><td>&nbsp;</td><td><b>Description</b></td><td>&nbsp;</td><td><b>Part No.</b></td><td>&nbsp;</td><td><b>Color</b></td><td>&nbsp;</td></tr>
      <tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>
      <tr><td>&nbsp;</td><td>Toaster</td><td>&nbsp;</td><td>2-Slice</td><td>&nbsp;</td><td>#25713</td><td>&nbsp;</td><td>Chorme</td><td>&nbsp;</td></tr>
   </table>
</div>'''

soup = BeautifulSoup(doc)
# find the table element in the HTML document
table = soup.find("table")
# grabs the top row
firstRow = table.contents[0]
# find how many columns there are
numberOfColumns = len(firstRow.contents)
restOfRows = table.contents[1:]
for row in restOfRows:
  for x in range(0,numberOfColumns):
    print "column data: %s" % row.contents[x].string

这个代码会从任何文档中提取出表格元素。接着,它会根据第一行来找出有多少列。最后,它会遍历剩下的每一行,把每行的数据打印出来。

有用的链接到Beautiful Soup的文档: http://www.crummy.com/software/BeautifulSoup/documentation.html

0

下面是用HTQL来实现的方法:

import htql;
doc = '''<div>     <table>
    <tr><td>&nbsp;</td><td><b>Item</b></td><td>&nbsp;</td><td><b>Description</b></td><td>&nbsp;        </td><td><b>Part No.</b></td><td>&nbsp;</td><td><b>Color</b></td><td>&nbsp;</td></tr>
    <tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>
    <tr><td>&nbsp;</td><td>Toaster</td><td>&nbsp;</td><td>2-Slice</td><td>&nbsp;</td><td>#25713</td><td>&nbsp;</td><td>Chorme</td><td>&nbsp;</td></tr>
  </table>  </div>''';

query = "<div>.<table>.<tr>{item=<td (th='Item')>&tx; desc=<td (th='Description')>&tx | item<>'Item'}";

for item, desc in htql.HTQL(doc, query): 
    print(item, desc); 

撰写回答