用BeautifulSoup解析HTML表格
我想从这个课程表中获取某一天的数据:点击这里
我已经用Beautiful Soup这个工具成功地把某一天(比如说星期一或'Mon')的整行数据添加到一个列表里,使用的代码如下:
from BeautifulSoup import BeautifulSoup
day ='Mon'
with open('timetable.txt', 'rt') as input_file:
html = input_file.read()
soup = BeautifulSoup(html)
#finds correct day tag
starttag = soup.find(text=day).parent.parent
print starttag
nexttag = starttag
row=[]
x = 0
#puts all td tags for that day in a list
while x < 18:
nexttag = nexttag.nextSibling.nextSibling
row.append(nexttag)
x += 1
print row
如你所见,这个命令返回了一个包含TD标签的列表,这些标签组成了课程表中'星期一'的那一行。
我的问题是,我不知道怎么进一步解析或搜索这个返回的列表,以找到相关的信息(比如COMP1740等课程代码)。
如果我能找到方法在列表中的每个元素里搜索课程代码,那么我就可以把这些代码和另一个时间列表结合起来,得到某一天的完整课程表。
欢迎任何帮助!(包括完全不同的方法)
2 个回答
0
from BeautifulSoup import BeautifulSoup
import re
#day input
day ='Thu'
#searches for a module (where html has rowspan="1")
module = re.compile(r'rowspan=\"1\"')
#lengths of module search (depending on html colspan attribute)
#1.5 hour
perlen15 = re.compile(r'colspan=\"3\"')
#2 hour
perlen2 = re.compile(r'colspan=\"4\"')
#2.5 hour etc.
perlen25 = re.compile(r'colspan=\"5\"')
perlen3 = re.compile(r'colspan=\"6\"')
perlen35 = re.compile(r'colspan=\"7\"')
perlen4 = re.compile(r'colspan=\"8\"')
#times correspond to first row of timetable.
times = ['8:00', '8:30', '9:00', '9:30', '10:00', '10:30', '11:00', '11:30', '12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00', '15:30']
#opens full timetable html
with open('timetable.txt', 'rt') as input_file:
html = input_file.read()
soup = BeautifulSoup(html)
#finds correct day tag
starttag = soup.find(text=day).parent.parent
nexttag = starttag
row=[]
#movement of cursor iterating over times list
curmv = 0
#puts following td tags for that day in a list
for time in times:
nexttag = nexttag.nextSibling.nextSibling
#detect if a module is found
found = module.search(repr(nexttag))
#detect length of that module
hour15 = perlen15.search(repr(nexttag))
hour2 = perlen2.search(repr(nexttag))
hour25 = perlen25.search(repr(nexttag))
hour3 = perlen3.search(repr(nexttag))
hour35 = perlen35.search(repr(nexttag))
hour4 = perlen4.search(repr(nexttag))
if found:
row.append(times[curmv])
row.append(nexttag)
if hour15:
curmv += 3
elif hour2:
curmv += 4
elif hour25:
curmv += 5
elif hour3:
curmv += 6
elif hour35:
curmv += 7
elif hour4:
curmv += 8
else:
curmv += 2
else:
curmv += 1
#write day to html file
with open('output.html', 'wt') as output_file:
for e in row:
output_file.write(str(e))
如你所见,这段代码可以区分一小时和两小时的讲座,还有一小时半、两小时半等不同长度的讲座。
我现在唯一的问题是第32行,我需要一个更好的方法来告诉代码什么时候停止在表格中横向移动,也就是:如何知道何时停止这个循环(在之前的代码中,我用的是 while x < 18:
,这只对星期一有效,因为那一行有18个
</tr>
标签时停止?
谢谢!
编辑:我打算尝试使用一个try和except块来捕捉当我把'times'设置到18:00时出现的错误。
编辑2:成功了! :D
1
你可以通过正则表达式来找到像课程编号这样的信息,也就是通过模式匹配来查找。
我不知道你对正则表达式了解多少,但Python里有一个叫're'的模块。比如说,我们要找的模式是“四个字母C-O-M-P后面跟着一个或多个数字”。这个模式用正则表达式表示就是COMP\d+
,其中\d
代表一个数字,而后面的+
表示要找尽可能多的数字(在这个例子里是4个)。
from BeautifulSoup import BeautifulSoup
import re
day ='Mon'
codePat = re.compile(r'COMP\d+')
with open('timetable.txt', 'rt') as input_file:
html = input_file.read()
soup = BeautifulSoup(html)
#finds correct day tag
starttag = soup.find(text=day).parent.parent
# print starttag
nexttag = starttag
row=[]
x = 0
#puts all td tags for that day in a list
while x < 18:
nexttag = nexttag.nextSibling.nextSibling
found = codePat.search(repr(nexttag))
if found:
row.append(found.group(0))
x += 1
print row
这样我就得到了输出,
['COMP1940', 'COMP1550', 'COMP1740']
就像我说的,我不知道你对正则表达式的了解程度,所以如果你能描述一下你想要的模式,我可以试着帮你写出来。如果你想自己动手,这里有一个不错的资源:点击这里。