使用美丽的汤解析蟒蛇

时间:2015-04-25 01:04:41

标签: python html beautifulsoup screen-scraping

我正在尝试解析餐厅结构不佳的网站并打印出如下菜单标题:

“Bento Box”, “Bara Chirashi set”, 等

我正在使用Python库Beautiful Soup,但我无法获得正确的输出:

import requests
from bs4 import BeautifulSoup

url = ('http://www.sushitaro.com/menu-lunch.html')
r = requests.get(url, auth=('user', 'pass'))

data = r.text

soup = BeautifulSoup(data)
dataList = list()

for string in soup.findAll('b'):
    dataList.append(string)

print(dataList)

这会返回太多元素,它们作为HTML返回而不仅仅是文本,而且文本内容本身对于unicode字符和多余的空格非常混乱。

我真的遇到了麻烦,所以任何帮助都会受到赞赏。

2 个答案:

答案 0 :(得分:1)

听起来您只想从相关网站获取菜单项的名称。页面抓取可能很棘手,除了学习库之外,还必须查看页面的结构。例如,在这里,价格也是粗体,所以如果您只想要菜单项的名称,您必须找到不同的区别特征。在这种情况下,网站设计师已经为每个菜单标题增加了一个字体大小,因此,按照您的代码通过“汤”的定义,您可以获取所有菜单标题:

import requests 
from bs4 import BeautifulSoup
url = ('http://www.sushitaro.com/menu-lunch.html')
r = requests.get(url, auth=('user', 'pass'))
data = r.text
soup = BeautifulSoup(data)

menuTitlesHTML = soup.findAll('font', {"size": "+1"})

现在,这将返回大量HTML而不仅仅是文本。我假设您熟悉Python列表推导,这在这里非常方便。如果您想要文本,可以尝试:

menuTitlesDirty = [titleHTML.text for titleHTML in menuTitlesHTML]

但是现在你会注意到这些标题有很多多余的空白,包括unicode和一些额外的字符,比如'@s'。由于您似乎只想要ASCII菜单标题,我们可以简单地转换为ASCII,忽略错误,以清除unicode。为此,我们可以将单个空格替换为捕获不需要的字符的正则表达式的匹配:换行符,空格和@s。为此,我们可以应用“.strip()”,删除字符串末尾的额外空格。总之,这是:

import re
badChars = re.compile('[\s@]+')
menuTitles = [badChars.sub(" ", dirtyTitle.encode('ascii', 'ignore')).strip() for dirtyTitle in menuTitlesDirty]

这会返回您想要的内容:

['Lunch Bento Box',
 'Bara Chirashi set',
 'Tekka Chirashi set',
 'Sushi Mori set',
 'Sushi Jo set',
 'Sushi Tokujo set',
 'Sashimi & Tempura Teishoku',
 'Tokujo Sashimi',
 "Today's Lunch Special",
 'Saba Shioyaki Teishoku',
 'Katsu Don set',
 'Tem Don set',
 'Cold Soba or Udon w/one topping',
 'Hot Soup Udon or Soba w/one Topping']

总结一下:页面抓取是一个混乱且反复的过程,您希望在页面上使用任何差异对您有利。 Python REPL真的是你的朋友,在这里。希望这能为您和其他人提供许多工具的概念,更普遍的是Python,特别是Beautiful Soup,可以帮助完成这个过程。

答案 1 :(得分:0)

我认为输出可能因为你打印的方式而难以辨认。

尝试:

for d in dataList:
    print(d)