Намерете следния етикет с pyparsing

Използвам pyparsing за анализ на HTML. Грабвам всички embed тагове, но в някои случаи има етикет a директно след него, който също искам да грабна, ако е наличен.

пример:

import pyparsing
target = pyparsing.makeHTMLTags("embed")[0]
target.setParseAction(pyparsing.withAttribute(src=pyparsing.withAttribute.ANY_VALUE))
target.ignore(pyparsing.htmlComment)

result = target.searchString(""".....
   <object....><embed>.....</embed></object><br /><a href="/bgblah">blah</a>
   """)

Не успях да намеря никакво отместване на знаци в резултатните обекти, в противен случай бих могъл просто да взема парче от оригиналния входен низ и да работя оттам.

РЕДАКТИРАНЕ:

Някой ме попита защо не използвам BeautifulSoup. Това е добър въпрос, позволете ми да ви покажа защо избрах да не го използвам с примерен код:

import BeautifulSoup
import urllib
import re
import socket

socket.setdefaulttimeout(3)

# get some random blogs
xml = urllib.urlopen('http://rpc.weblogs.com/shortChanges.xml').read()

success, failure = 0.0, 0.0

for url in re.compile(r'\burl="([^"]+)"').findall(xml)[:30]:
    print url
    try:
        BeautifulSoup.BeautifulSoup(urllib.urlopen(url).read())
    except IOError:
        pass
    except Exception, e:
        print e
        failure += 1
    else:
        success += 1


print failure / (failure + success)

Когато опитам това, BeautifulSoup се проваля с грешки при анализ 20-30% от времето. Това не са редки крайни случаи. pyparsing е бавен и тромав, но не се е взривил, независимо какво хвърлям към него. Ако мога да бъда просветен за по-добър начин за използване на BeautifulSoup, тогава наистина ще ми е интересно да знам това.


person ʞɔıu    schedule 20.11.2009    source източник
comment
Това е много странно: използвах точния ви код, пуснах го в три различни момента и той успешно анализира всички 90 URL адреса, които се получиха. Използвам Python 2.5.4 на Windows с BeautifulSoup 3.0.7a. Какви грешки виждате?   -  person Ned Batchelder    schedule 20.11.2009
comment
python 2.5.1 на OS X, BeautifulSoup 3.1.0.1. Най-често срещаните грешки са bad end tag: u"</scr' + 'ipt>" и malformed start tag.   -  person ʞɔıu    schedule 20.11.2009


Отговори (4)


Ако има незадължителен <a> таг, който би бил интересен, ако следва <embed> таг, тогава го добавете към вашия шаблон за търсене:

embedTag = pyparsing.makeHTMLTags("embed")[0]
aTag = pyparsing.makeHTMLTags("a")[0]
target = embedTag + pyparsing.Optional(aTag)
result = target.searchString(""".....   
    <object....><embed>.....</embed></object><br /><a href="/bgblah">blah</a>
    """)

print result.dump()

Ако искате да уловите местоположението на знака на израз във вашия анализатор, вмъкнете едно от тези с име на резултата:

loc = pyparsing.Empty().setParseAction(lambda s,locn,toks: locn)
target = loc("beforeEmbed") + embedTag + loc("afterEmbed") + 
                                                 pyparsing.Optional(aTag)
person PaulMcG    schedule 20.11.2009
comment
Нещото loc проработи, но изглежда не можах да накарам опцията да работи. Сигурни ли сте, че примерният код работи? - person ʞɔıu; 20.11.2009
comment
Е, този пример не работи, защото маркерът <a> не следва непосредствено етикета <embed>. Не разбрах какво имаш предвид под следвам. Какво имате предвид под следвам? - person PaulMcG; 21.11.2009
comment
В примера тагът за вграждане е последван от някои неща, показани с елипси, таг за близко вграждане, таг за близък обект, празен таг BR и след това таг A. - person PaulMcG; 21.11.2009
comment
мога ли да направя нещо като embedTag + skipTo(endEmbedTag) + Optional(endObjectTag + brTag + aTag)? - person ʞɔıu; 22.11.2009
comment
embedTag + pyparsing.SkipTo(endEmbedTag, include=True) + pyparsing.Optional(endObjectTag + brTag + aTag) трябва да работи за този конкретен случай. Но не бих се изненадал, ако вашият HTML имаше други тагове на непредсказуеми места. Ако искате да съпоставите етикет <embed>, който е последван от маркер <a>, това може да е малко по-стабилно: embedTag + pyparsing.SkipTo(aTag, failOn=embedTag) + aTag | embedTag. В този случай SkipTo преминава директно към следващия aTag, но не успява, ако първо има друг embedTag. Но аз съм в Pure Speculation Land тук, така че трябва да попълните останалото. - person PaulMcG; 22.11.2009

Защо бихте написали свой собствен HTML анализатор? Стандартната библиотека включва HTMLParser и BeautifulSoup може да се справи с всяка задача, която HTMLParser не може.

person Ned Batchelder    schedule 20.11.2009
comment
Знам какво е pyparsing, просто се чудя защо бихте го използвали за обърканата работа по анализиране на HTML, когато вече съществуват съществуващи специализирани модули. - person Ned Batchelder; 20.11.2009
comment
Актуализирах въпроса с причината, поради която не използвам BeautifulSoup. Кратък отговор: защото BeautifulSoup получава много грешки при анализиране, но аз нямам същия проблем с pyparsing. Ако има по-добър начин за използване на BeautifulSoup, за който не знам или има нещо друго, което пропускам, наистина ще ми е интересно да науча за това. - person ʞɔıu; 20.11.2009

не предпочитате да използвате нормален регулярен израз? или защото има лош навик да анализира html? :Д

re.findall("<object.*?</object>(?:<br /><a.*?</a>)?",a)
person YOU    schedule 20.11.2009
comment
всички в SO вече знаят, че анализирането на HTML с регулярен израз е престъпление срещу човека; цитиране: stackoverflow.com/questions/1732348/ - person ʞɔıu; 20.11.2009
comment
:D Виждам, това е първото ми впечатление за тези 2 дни, когато и аз се включих. - person YOU; 20.11.2009
comment
Всъщност не съм против използването на регулярен израз сам по себе си, но съм използвал този подход в миналото и се опитвам да науча по-добър начин. Бих могъл да направя това, но все пак ще имам нужда/искам анализатор, който да анализира HTML атрибутите и т.н. и може да се окаже, че използвам хибриден подход, използвайки по малко от двете. - person ʞɔıu; 20.11.2009

Успях да стартирам кода на BeautifulSoup и не получих грешки. Работя с BeautifulSoup 3.0.7a

Моля, използвайте BeautifulSoup 3.0.7a; 3.1.0.1 има грешки, които не му позволяват да работи изобщо в някои случаи (като вашия).

person gibson    schedule 20.11.2009
comment
Бих добавил това като коментар към първия въпрос, но нямам достатъчно представител. - person gibson; 20.11.2009