Python BeautifulSoup 自动跟踪内容表格的行和列
首先让我说,我是新来的,对Stack和Python都不太熟悉。上周才开始接触它。不过,我在PHP、C++、Pascal、ADA、B和Forth方面有不少经验(这显示了我的年龄)。
我写了一个脚本,从一个网站上提取产品页面,并把它们存储在本地的MySQL数据库里。这样做是为了在晚上网站负载较轻的时候进行抓取。现在我需要从每个页面的HTML中提取产品描述。这些描述是放在表格里的。不过,每个页面的相关信息可能在不同的行和列中。
我可以确定的几点是:
- 每个表格都有一个标题,说明下面行和列的数据。
- 标题的文字是固定的,比如“Part”总是指零件类型,而“Part No.”总是指零件编号。
- 并不是所有页面都会包含所有想要的数据。如果找不到某些数据,就只能保存找到的内容。
下面的部分是我遇到问题的地方,如何从一行中选择第n列?
我现在的做法是:
获取所需的列
- 从数据库中获取HTML文档
- 抓取表格(我的表格总是位于页面唯一的div中)
- 抓取所有行(其实只需要处理第一行)
- 对于每一行,当我找到想要的字段名称时,记录下行和列的索引。
获取数据值
- 对于每一行:
- 如果是标题行就跳过(记录下包含标题字段的行数)
- 对于每一列,抓取文本值。
- 把这些值保存到数据库中。
我页面中重要的部分看起来是这样的:
<div>
...
<table>
<tr><td> </td><td><b>Item</b></td><td> </td><td><b>Description</b></td><td> </td><td><b>Part No.</b></td><td> </td><td><b>Color</b></td><td> </td></tr>
<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
<tr><td> </td><td>Toaster</td><td> </td><td>2-Slice</td><td> </td><td>#25713</td><td> </td><td>Chorme</td><td> </td></tr>
</table>
...
</div>
非常感谢任何回复的人。
2 个回答
0
这是我处理这个问题的方法:
from BeautifulSoup import BeautifulSoup
doc = '''<div>
<table>
<tr><td> </td><td><b>Item</b></td><td> </td><td><b>Description</b></td><td> </td><td><b>Part No.</b></td><td> </td><td><b>Color</b></td><td> </td></tr>
<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
<tr><td> </td><td>Toaster</td><td> </td><td>2-Slice</td><td> </td><td>#25713</td><td> </td><td>Chorme</td><td> </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> </td><td><b>Item</b></td><td> </td><td><b>Description</b></td><td> </td><td><b>Part No.</b></td><td> </td><td><b>Color</b></td><td> </td></tr>
<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
<tr><td> </td><td>Toaster</td><td> </td><td>2-Slice</td><td> </td><td>#25713</td><td> </td><td>Chorme</td><td> </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);