所以当我决定解析网站上的内容时。例如,http://allrecipes.com/Recipe/Slow-Cooker-Pork-Chops-II/Detail.aspx
我想将成分解析成文本文件。成分位于:
< div class =“ingredients” style =“margin-top:10px;”>
并且在此之内,每种成分都存储在
之间< li class =“plaincharacterwrap”>
有人很好地使用正则表达式提供代码,但是当你从一个站点到另一个站点进行修改时会让人感到困惑。所以我想使用Beautiful Soup,因为它有很多内置功能。除了我可以对如何实际操作感到困惑。
代码:
import re
import urllib2,sys
from BeautifulSoup import BeautifulSoup, NavigableString
html = urllib2.urlopen("http://allrecipes.com/Recipe/Slow-Cooker-Pork-Chops-II/Detail.aspx")
soup = BeautifulSoup(html)
try:
ingrdiv = soup.find('div', attrs={'class': 'ingredients'})
except IOError:
print 'IO error'
这是怎么开始的?我想找到实际的div类,然后解析li类中的所有成分。
任何帮助将不胜感激!谢谢!
答案 0 :(得分:4)
import urllib2
import BeautifulSoup
def main():
url = "http://allrecipes.com/Recipe/Slow-Cooker-Pork-Chops-II/Detail.aspx"
data = urllib2.urlopen(url).read()
bs = BeautifulSoup.BeautifulSoup(data)
ingreds = bs.find('div', {'class': 'ingredients'})
ingreds = [s.getText().strip() for s in ingreds.findAll('li')]
fname = 'PorkChopsRecipe.txt'
with open(fname, 'w') as outf:
outf.write('\n'.join(ingreds))
if __name__=="__main__":
main()
结果
1/4 cup olive oil
1 cup chicken broth
2 cloves garlic, minced
1 tablespoon paprika
1 tablespoon garlic powder
1 tablespoon poultry seasoning
1 teaspoon dried oregano
1 teaspoon dried basil
4 thick cut boneless pork chops
salt and pepper to taste
对@eyquem的跟进回复:
from time import clock
import urllib
import re
import BeautifulSoup
import lxml.html
start = clock()
url = 'http://allrecipes.com/Recipe/Slow-Cooker-Pork-Chops-II/Detail.aspx'
data = urllib.urlopen(url).read()
print "Loading took", (clock()-start), "s"
# by regex
start = clock()
x = data.find('Ingredients</h3>')
patingr = re.compile('<li class="plaincharacterwrap">\r\n +(.+?)</li>\r\n')
res1 = '\n'.join(patingr.findall(data,x))
print "Regex parse took", (clock()-start), "s"
# by BeautifulSoup
start = clock()
bs = BeautifulSoup.BeautifulSoup(data)
ingreds = bs.find('div', {'class': 'ingredients'})
res2 = '\n'.join(s.getText().strip() for s in ingreds.findAll('li'))
print "BeautifulSoup parse took", (clock()-start), "s - same =", (res2==res1)
# by lxml
start = clock()
lx = lxml.html.fromstring(data)
ingreds = lx.xpath('//div[@class="ingredients"]//li/text()')
res3 = '\n'.join(s.strip() for s in ingreds)
print "lxml parse took", (clock()-start), "s - same =", (res3==res1)
给出
Loading took 1.09091222621 s
Regex parse took 0.000432703726233 s
BeautifulSoup parse took 0.28126133314 s - same = True
lxml parse took 0.0100940499505 s - same = True
正则表达式要快得多(除非它错了);但是如果考虑加载页面并将其解析在一起,BeautifulSoup仍然只占运行时的20%。如果你非常关心速度,我建议使用lxml。
答案 1 :(得分:2)
是的,必须为每个站点编写特殊的正则表达式模式。
但我认为
1-使用Beautiful Soup进行的治疗也必须适应每个地点。
2-regexes写起来并不复杂,并且有一点习惯,可以快速完成
我很想知道必须用Beautiful Soup进行什么样的治疗才能获得与我在几分钟内获得的结果相同的结果。曾几何时,我试着学习美丽的汤,但我并没有对这个烂摊子说些什么。我应该再试一次,现在我对Python更熟练了。但到目前为止,正则表达式对我来说已经足够了
以下是此新网站的代码:
import urllib
import re
url = 'http://allrecipes.com/Recipe/Slow-Cooker-Pork-Chops-II/Detail.aspx'
sock = urllib.urlopen(url)
ch = sock.read()
sock.close()
x = ch.find('Ingredients</h3>')
patingr = re.compile('<li class="plaincharacterwrap">\r\n +(.+?)</li>\r\n')
print '\n'.join(patingr.findall(ch,x))
我下载并安装了BeautifulSoup并与正则表达式进行了比较。
我认为我的比较代码中没有任何错误
import urllib
import re
from time import clock
import BeautifulSoup
url = 'http://allrecipes.com/Recipe/Slow-Cooker-Pork-Chops-II/Detail.aspx'
data = urllib.urlopen(url).read()
te = clock()
x = data.find('Ingredients</h3>')
patingr = re.compile('<li class="plaincharacterwrap">\r\n +(.+?)</li>\r\n')
res1 = '\n'.join(patingr.findall(data,x))
t1 = clock()-te
te = clock()
bs = BeautifulSoup.BeautifulSoup(data)
ingreds = bs.find('div', {'class': 'ingredients'})
ingreds = [s.getText().strip() for s in ingreds.findAll('li')]
res2 = '\n'.join(ingreds)
t2 = clock()-te
print res1
print
print res2
print
print 'res1==res2 is ',res1==res2
print '\nRegex :',t1
print '\nBeautifulSoup :',t2
print '\nBeautifulSoup execution time / Regex execution time ==',t2/t1
结果
1/4 cup olive oil
1 cup chicken broth
2 cloves garlic, minced
1 tablespoon paprika
1 tablespoon garlic powder
1 tablespoon poultry seasoning
1 teaspoon dried oregano
1 teaspoon dried basil
4 thick cut boneless pork chops
salt and pepper to taste
1/4 cup olive oil
1 cup chicken broth
2 cloves garlic, minced
1 tablespoon paprika
1 tablespoon garlic powder
1 tablespoon poultry seasoning
1 teaspoon dried oregano
1 teaspoon dried basil
4 thick cut boneless pork chops
salt and pepper to taste
res1==res2 is True
Regex : 0.00210892725193
BeautifulSoup : 2.32453566026
BeautifulSoup execution time / Regex execution time == 1102.23605776
没有评论!
我意识到在我的代码中我没有使用正则表达式,我使用了一个使用正则表达式和 find()的方法。
这是我使用正则表达式时使用的方法,因为它在某些情况下提高了治疗速度。这是由于 find()功能极快地运行。
要知道我们要比较什么,我们需要以下代码。
在代码3和代码4中,我在另一个帖子中考虑了Achim的评论:使用re.IGNORECASE和re.DOTALL, [“\'] 而不是” 强>
这些代码是分开的,因为它们必须在不同的文件中执行才能获得可靠的结果:我不知道为什么,但是如果所有代码都在同一个文件中执行,那么某些结果时间就会大不相同(0.00075而不是0.0022例如
import urllib
import re
import BeautifulSoup
from time import clock
url = 'http://allrecipes.com/Recipe/Slow-Cooker-Pork-Chops-II/Detail.aspx'
data = urllib.urlopen(url).read()
# Simple regex , without x
te = clock()
patingr = re.compile('<li class="plaincharacterwrap">\r\n +(.+?)</li>\r\n')
res0 = '\n'.join(patingr.findall(data))
t0 = clock()-te
print '\nSimple regex , without x :',t0
和
# Simple regex , with x
te = clock()
x = data.find('Ingredients</h3>')
patingr = re.compile('<li class="plaincharacterwrap">\r\n +(.+?)</li>\r\n')
res1 = '\n'.join(patingr.findall(data,x))
t1 = clock()-te
print '\nSimple regex , with x :',t1
和
# Regex with flags , without x and y
te = clock()
patingr = re.compile('<li class=["\']plaincharacterwrap["\']>\r\n +(.+?)</li>\r\n',
flags=re.DOTALL|re.IGNORECASE)
res10 = '\n'.join(patingr.findall(data))
t10 = clock()-te
print '\nRegex with flags , without x and y :',t10
和
# Regex with flags , with x and y
te = clock()
x = data.find('Ingredients</h3>')
y = data.find('h3>\r\n Footnotes</h3>\r\n')
patingr = re.compile('<li class=["\']plaincharacterwrap["\']>\r\n +(.+?)</li>\r\n',
flags=re.DOTALL|re.IGNORECASE)
res11 = '\n'.join(patingr.findall(data,x,y))
t11 = clock()-te
print '\nRegex with flags , without x and y :',t11
和
# BeautifulSoup
te = clock()
bs = BeautifulSoup.BeautifulSoup(data)
ingreds = bs.find('div', {'class': 'ingredients'})
ingreds = [s.getText().strip() for s in ingreds.findAll('li')]
res2 = '\n'.join(ingreds)
t2 = clock()-te
print '\nBeautifulSoup :',t2
结果
Simple regex , without x : 0.00230488284125
Simple regex , with x : 0.00229121279385
Regex with flags , without x and y : 0.00758719458758
Regex with flags , with x and y : 0.00183724493364
BeautifulSoup : 2.58728860791
使用x对简单正则表达式的速度没有影响。
带有标志的正则表达式,没有x和y,执行时间更长,但结果与其他结果不同,因为它捕获了一大块补充文本。这就是为什么在实际的应用程序中,应该使用带有标志和x / y的正则表达式。
带有标志和x和y的更复杂的正则表达式花费的时间减少了20%。
嗯,无论是否有x / y,结果都没有太大变化。
所以我的结论是一样的
使用正则表达式,诉诸于 find()与BeautifulSoup相比,大约快了1000倍, 而我估计要快100倍 lxml(我没有安装lxml)
对于你所写的,休,我会说:
当正则表达式出错时,它不会更快或更慢。它没有运行。
当正则表达式出错时,编码器会使它变得正确,就是这样。
我不明白为什么stackoverflow.com上有95%的人想要说服其他5%的人不得使用正则表达式来分析HTML或XML或其他任何内容。我说“分析”,而不是“解析”。据我所知,解析器首先分析文本的整体,然后显示我们想要的元素的内容。相反,正则表达式适用于搜索的内容,它不会构建HTML / XML文本的树或解析器的其他任何内容,而且我不太了解。
所以,我对正则表达式非常满意。即使是非常长的RE也没有问题,正则表达式允许我运行在分析文本后必须迅速做出反应的程序。 BS或lxml会起作用,但那会很麻烦。
我还有其他意见要做,但我没有时间讨论一个主题,事实上,我让别人按照自己的意愿去做。