RE und html...

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 6. August 2007, 17:24

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?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 6. August 2007, 17:33

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 ;)

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Montag 6. August 2007, 20:13

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.
Zuletzt geändert von HWK am Montag 6. August 2007, 21:12, insgesamt 2-mal geändert.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Montag 6. August 2007, 20:36

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
BlackJack

Montag 6. August 2007, 21:17

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))
thelittlebug
User
Beiträge: 188
Registriert: Donnerstag 20. Juli 2006, 20:46
Wohnort: Wien
Kontaktdaten:

Montag 6. August 2007, 22:25

Code: Alles auswählen

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

Montag 6. August 2007, 23:02

Da kann man noch das `compile()` rausnehmen:

Code: Alles auswählen

dict(re.findall(r"(\w+)\s*=\s*['\"]*([^'\"]+)['\"]*;", txt))
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 7. August 2007, 07:22

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.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Dienstag 7. August 2007, 12:31

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
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 13. August 2007, 13:19

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 ;)

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Montag 13. August 2007, 13:54

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!"'. :-)
Antworten