Python HTML анализирует конкретную информацию в тегах - PullRequest
1 голос
/ 11 апреля 2011

Я пытаюсь разобрать конкретную информацию в тегах.

Например, на веб-сайте:

http://www.epicurious.com/articlesguides/bestof/toprecipes/bestchickenrecipes/recipes/food/views/My-Favorite-Simple-Roast-Chicken-231348

Я пытаюсь разобрать очень специфическую информацию, например, ингредиенты.Если вы перейдете к источнику страниц, то увидите, что представленная информация находится внутри тегов, называемых

<h2>Ingredients</h2>, а <ul class="ingredientsList"> содержит все фактические ингредиенты.

В Интернете я нашел программу на python, котораяудобно разбирает гиперссылки на сайте.Но я хочу изменить это, чтобы разобрать эти ингредиенты.Я не очень хорошо разбираюсь в python, но как именно я могу изменить свой код, чтобы он соответствовал моим потребностям в разборе?

Пожалуйста, уточните, как мне поступить, или предоставив примеры и т. Д., Было бы очень признательноЯ не очень осведомлен об этом.

Код:

import sgmllib

class MyParser(sgmllib.SGMLParser):
    "A simple parser class."

    def parse(self, s):
        "Parse the given string 's'."
        self.feed(s)
        self.close()

    def __init__(self, verbose=0):
        "Initialise an object, passing 'verbose' to the superclass."

        sgmllib.SGMLParser.__init__(self, verbose)
        self.hyperlinks = []
        self.descriptions = []
        self.inside_a_element = 0
        self.starting_description = 0

    def start_a(self, attributes):
        "Process a hyperlink and its 'attributes'."

        for name, value in attributes:
            if name == "href":
                self.hyperlinks.append(value)
                self.inside_a_element = 1
                self.starting_description = 1

    def end_a(self):
        "Record the end of a hyperlink."

        self.inside_a_element = 0

    def handle_data(self, data):
        "Handle the textual 'data'."

        if self.inside_a_element:
            if self.starting_description:
                self.descriptions.append(data)
                self.starting_description = 0
            else:
                self.descriptions[-1] += data

    def get_hyperlinks(self):
        "Return the list of hyperlinks."

        return self.hyperlinks

    def get_descriptions(self):
        "Return a list of descriptions."

        return self.descriptions

import urllib, sgmllib

# Get something to work with.
f = urllib.urlopen("http://www.epicurious.com/Roast-Chicken-231348")
s = f.read()

# Try and process the page.
# The class should have been defined first, remember.
myparser = MyParser()
myparser.parse(s)

# Get the hyperlinks.
print myparser.get_hyperlinks()
print myparser.get_descriptions()

Ответы [ 2 ]

3 голосов
/ 11 апреля 2011

Посмотрите на http://www.crummy.com/software/BeautifulSoup/ Ваш подход работает для простых случаев, но вызовет головную боль, как только HTML и / или ваши требования станут немного сложнее.

1 голос
/ 11 апреля 2011

Я получу галочку от всех людей, которые говорят, что тексты HTML не могут быть проанализированы с помощью регулярных выражений.

Хорошо, хорошо, но я получил результат через пятьдесят минут:

Во-первых, я использовал этот код для удобного отображения исходного кода веб-страницы:

import urllib

url = ('http://www.epicurious.com/articlesguides/bestof/'
       'toprecipes/bestchickenrecipes/recipes/food/views/'
       'My-Favorite-Simple-Roast-Chicken-231348')


sock = urllib.urlopen(url)
ch = sock.read()
sock.close()


gen = (str(i)+' '+repr(line) for i,line in enumerate(ch.splitlines(1)))

print '\n'.join(gen)

Затем игра для детей - поймать ингредиенты:

import urllib
import re

url = ('http://www.epicurious.com/articlesguides/bestof/'
       'toprecipes/bestchickenrecipes/recipes/food/views/'
       'My-Favorite-Simple-Roast-Chicken-231348')

sock = urllib.urlopen(url)
ch = sock.read()
sock.close()

x = ch.find('ul class="ingredientsList">')

patingr = re.compile('<li class="ingredient">(.+?)</li>\n')

print patingr.findall(ch,x)

.

РЕДАКТИРОВАТЬ

Ахим,

Что касается наличия '\ n', то моя вина, а не инструмент regex: я написал код слишком быстро.

Вы правы в отношении заглавных букв: BS по-прежнему находит правильные строки, в то время как регулярное выражение не выполняется.Но я никогда не видел исходный код, в котором теги элементов были написаны в верхнем регистре.Можете ли вы дать мне ссылку на такой?

Относительно ' или ", то же самое, я никогда не вижу, но вы правы, это может произойти.

Однако при написании RE, если есть верхний регистрбуквы или ' вместо " в некоторых местах, RE будет записан для их соответствия: в чем проблема?

Вы имеете в виду: если исходный код изменится?Еще менее вероятно увидеть в один прекрасный день сайт, исходный код которого изменится с нижнего на верхний регистр или " будет изменен на '.Это не очень реалистично.

Таким образом, легко исправить мой результат RE

import urllib
import re

url = ('http://www.epicurious.com/articlesguides/bestof/'
       'toprecipes/bestchickenrecipes/recipes/food/views/'
       'My-Favorite-Simple-Roast-Chicken-231348')

sock = urllib.urlopen(url)
ch = sock.read()
sock.close()

#----------------------------------------------------------
patingr = re.compile('<li class="ingredient">(.+?)</li>\n')
print
print '\n'.join(repr(mat.group()) for mat in patingr.finditer(ch))


ch = ch.replace('<li class="ingredient">One 2- to 3-pound farm-raised chicken</li>',
                "<LI class='ingredient'>One 2- to 3-pound farm-raised \nchicken</li>")
print
print '\n'.join(repr(mat.group()) for mat in patingr.finditer(ch))


patingr = re.compile('<li class=["\']ingredient["\']>(.+?)</li>\n',re.DOTALL|re.IGNORECASE)
print
print '\n'.join(repr(mat.group()) for mat in patingr.finditer(ch))

'<li class="ingredient">One 2- to 3-pound farm-raised chicken</li>\n'
'<li class="ingredient">Kosher salt and freshly ground black pepper</li>\n'
'<li class="ingredient">2 teaspoons minced thyme (optional)</li>\n'
'<li class="ingredient">Unsalted butter</li>\n'
'<li class="ingredient">Dijon mustard</li>\n'

'<li class="ingredient">Kosher salt and freshly ground black pepper</li>\n'
'<li class="ingredient">2 teaspoons minced thyme (optional)</li>\n'
'<li class="ingredient">Unsalted butter</li>\n'
'<li class="ingredient">Dijon mustard</li>\n'

"<LI class='ingredient'>One 2- to 3-pound farm-raised \nchicken</li>\n"
'<li class="ingredient">Kosher salt and freshly ground black pepper</li>\n'
'<li class="ingredient">2 teaspoons minced thyme (optional)</li>\n'
'<li class="ingredient">Unsalted butter</li>\n'
'<li class="ingredient">Dijon mustard</li>\n'

Затем, с этого момента, я всегда буду добавлятьфлаг re.IGNORECASE и ["'] в тегах

Могут ли возникнуть другие "проблемы"?Мне было бы интересно узнать о них.

Я не претендую на то, что регулярные выражения должны использоваться во всех случаях, а синтаксические анализаторы никогда, я просто думаю, что если условия для использования регулярных выражений в контролируемом и ограниченном видепроверены, они очень интересны, и пренебрегать ими было бы жалко.

Кстати, вы ничего не говорите о том факте, что регулярные выражения работают намного быстрее, чем BeautifulSoup.См. сравнение времени между регулярным выражением и BeautifulSoup

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...