Seite 1 von 1

RE und html...

Verfasst: Montag 6. August 2007, 17:24
von jens
Ich weiß normalerweise sollte man BeautifulSoup nehmen, hab ich aber nicht ;)

Deswegen versuche ich es mit einer RE, aber es klappt nicht richtig:

Code: Alles auswählen

import re

txt = """...</form>
</fieldset>

<script language="javascript" type="text/javascript" src="/media/PyLucid/sha1.js"></script>

<script type="text/javascript">
    debug_msg = true;
    salt = 'dfe08';
    challenge = 'debug';
    submit_url = '.';
    focus_id = 'plaintext_pass';
    init();
</script>
</div>

<p id="footer">
   powered by <a href="http://www.pylucid.org">PyLucid v0.8.0 alpha3SVN</a> | <a href="/_command/1/auth/login/">Log in</a> | Rendered in render time: 0.223 - overall: 0.2 - Queries: 16 sec. | last modified: 2007-06-26 01:30:09
</p>"""


regex = re.compile(r'<script [^>]+?(.+?)<\/script>(?uimx)')

print regex.findall(txt)
ich brauche die Zeilen aus dem Beispielcode:

Code: Alles auswählen

    debug_msg = true;
    salt = 'dfe08';
    challenge = 'debug';
    submit_url = '.';
    focus_id = 'plaintext_pass';
    init();
Meine RE trifft aber nur auf den ersten <script> Tag :( Kann mir jemand helfen?

Verfasst: Montag 6. August 2007, 17:33
von jens
Ah, ich habs:

Code: Alles auswählen

regex1 = re.compile(
    r'<script [^>]+?'
    '(?P<code>.+?)'
    '<\/script>'
    '(?uisx)'
)
regex2 = re.compile(r'(.+?)=(.+?);')


JS_data = {}
for line in regex1.findall(txt):
    for line2 in regex2.findall(line):
        key, value = line2
        key = key.strip(" '")
        value = value.strip(" '")
        JS_data[key] = value

print JS_data
Ausgabe:

Code: Alles auswählen

{'submit_url': '.', 'focus_id': 'plaintext_pass', 'debug_msg': 'true', 'salt': 'dfe08', 'challenge': 'debug'}
Schön ist es nicht, funktioniert aber... Könnte man sicherlich auch mit einigen Tricks mit einer einzigen RE lösen... Wenn jemand lust dazu hat, immer her damit ;)

Verfasst: Montag 6. August 2007, 20:13
von HWK
Z.B. so:

Code: Alles auswählen

regex = re.compile(r'<script .+>\n?((.+\n?)+)</script>(?imux)')
MfG
HWK

Edit: Viel besser ist aber

Code: Alles auswählen

regex = re.compile(r'<script .+?>(.*?)</script>(?imuxs)')
Das entscheidende ist das s in (?imuxs) für DOTALL.

Verfasst: Montag 6. August 2007, 20:36
von EnTeQuAk
Und um den Wunsch nach einer möglichst kurzen Lösung zu stillen:

Code: Alles auswählen

In [40]: dict(
    [(x.strip('\'"; '), y.strip('\'"; ')) for x, y in 
        [z.split('=') for z in re.compile(r'<script .+>\n?((.+\n?)+)</script>(?imux)').search(txt).group(1).split('\n') if len(z.split('='))>1]
    ]
)
Habe es nicht viel kürzer hinbekommen :)


MfG EnTeQuAk

Verfasst: Montag 6. August 2007, 21:17
von BlackJack
Es geht 20 Zeichen kürzer. Ich habe zum Vergleich aus Deiner Lösung alle überflüssigen Leerzeichen und Zeilenumbrüche entfernt.

Code: Alles auswählen

dict((x.strip('\'"; ') for x in y) for y in (z.split('=') for z in re.search(r'<script .+>\n?((.+\n?)+)</script>(?imux)', txt).group(1).split('\n') if len(z.split('='))>1))

Verfasst: Montag 6. August 2007, 22:25
von thelittlebug

Code: Alles auswählen

print dict(re.compile(r"(\w+)\s*=\s*['\"]*([^'\"]+)['\"]*;").findall(txt))
lgherby

Verfasst: Montag 6. August 2007, 23:02
von BlackJack
Da kann man noch das `compile()` rausnehmen:

Code: Alles auswählen

dict(re.findall(r"(\w+)\s*=\s*['\"]*([^'\"]+)['\"]*;", txt))

Verfasst: Dienstag 7. August 2007, 07:22
von jens
Perfekt. Danke euch... Trift zwar auf mehr Dinge in der HTML Datei zu, als nur die Teile innerhalb eines <script> Tags, aber für meinen Fall ist das egal.

Verfasst: Dienstag 7. August 2007, 12:31
von HWK
Jetzt sollte es nur auf den Inhalt eines <script>-Tags zutreffen. Ist zwar etwas länger, aber vielleicht doch interessant:

Code: Alles auswählen

[dict(re.findall(r'(\w+)\s*=\s*[\'"]*([^\'"]+)[\'"]*;', x))
 for x in re.findall(r'<script .+?>(.*?)</script>(?imuxs)', txt)]
MfG
HWK

Verfasst: Montag 13. August 2007, 13:19
von jens
Thx. Ich hab es allerdings doch noch ein wenig Aufgebröselt:

Code: Alles auswählen

js_regex1 = re.compile(r'<script .+?>(.*?)</script>(?imuxs)')
js_regex2 = re.compile(r"(\w+)\s*=\s*['\"]*([^'\"]+)['\"]*;")

def _get_JS_data(content):
    """
    retuned the JS variable statements from the given html page content.
    """
    result = {}
    for txt in js_regex1.findall(content):
        data = dict(js_regex2.findall(txt))
        result.update(data)
        
    return result
Findet zwar eigentlich immer noch zuviel. Aber es stecken die wichtigen Daten drin ;)

Verfasst: Montag 13. August 2007, 13:54
von BlackJack
Musst Du nur noch hoffen, dass nie Zeichenketten vorkommen, bei denen es Probleme mit Anführungszeichen geben kann. Also zum Beispiel 'O\'Reilly' oder 'The knights who say "Ni!"'. :-)