Eine Frage zu Regex-Modul

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
LiorR91
User
Beiträge: 5
Registriert: Sonntag 1. Juli 2018, 15:43

Hallo :)

könnte mir jemand bitte erklären wie ich aus diesem Code:

Code: Alles auswählen

import re

string = "<b>foo</b> text text <b>bar</b> text text <b>foo</b>"
matches = re.findall(r'<b>[a-zA-Z]+</b>', string)
alle Treffer von foo und bar in die Liste 'matches' einfügen kann?

erwünschter Output:
print(matches)
# ['<b>foo</b>', '<b>bar</b>', <b>foo</b>']

tatsächlicher Output:
print(matches)
# ['<b>foo</b>', '<b>bar</b>']

Danke :)
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Also bei mir kommt da was anderes heraus als Du behauptest:

Code: Alles auswählen

In [162]: re.findall(r'<b>[a-zA-Z]+</b>', string)
Out[162]: ['<b>foo</b>', '<b>bar</b>', '<b>foo</b>']
Aber Du willst auch kein HTML mit regulären Ausdrücken verarbeiten. Dafür gibt es HTML-Parser:

Code: Alles auswählen

In [169]: from lxml import html

In [170]: html.fromstring(string)
Out[170]: <Element span at 0xaa71425c>

In [171]: html.fromstring(string).xpath('b')
Out[171]: [<Element b at 0xce164dc>, <Element b at 0xd04b784>, <Element b at 0xd04b39c>]

In [172]: html.fromstring(string).xpath('b/text()')
Out[172]: ['foo', 'bar', 'foo']
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
LiorR91
User
Beiträge: 5
Registriert: Sonntag 1. Juli 2018, 15:43

hmm okay. ich werde es mal nachschauen. Danke!
LiorR91
User
Beiträge: 5
Registriert: Sonntag 1. Juli 2018, 15:43

Hallo, ich bin wieder da.

Also ich habe das html Modul ausprobiert, bekomme aber das gleiche Problem. HTML Code:

Code: Alles auswählen

<a href="/unwantedtext/bar">

<tbody>                    
    <tr class='whocares' 
        <td class="datatable-item-first" style="max-width: 120px; overflow: hidden;">
            <a href="/foo/bar">
                  <b>foobar</b>  
            </a>
	</td>
        ....
		
	<td class="datatable-item-first" style="max-width: 120px; overflow: hidden;">
            <a href="/something/bar">
                  <b>foobar</b>  
            </a>
	</td>
		
		
	<td class="datatable-item-first" style="max-width: 120px; overflow: hidden;">
            <a href="/foo/bar">
                  <b>foobar</b>  
            </a>
	</td>
		
		
	....
    </tr>
</tbody>

....

....

....
<a style="" href='/foo/bar' >Unnötige Info </a><br />
und ich habe erfolgreich die relevante Infos herausgezogen mit:

Code: Alles auswählen

list = tree.xpath('.//a[contains(@href,"/bar") and not(.//@style) and not (contains(@href, "unwantedtext"))]/@href')
aber wieder bekomme ich statt:

Code: Alles auswählen

print(list)
# ['/foo/bar', '/something/bar', '/foo/bar']
das:

Code: Alles auswählen

print(list)
# ['/foo/bar', '/something/bar']
:?: :cry:
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Also bei dem gezeigten HTML-Fragment bekomme ich das richtige raus:

Code: Alles auswählen

In [6]: doc = html.fromstring(source)

In [7]: doc.xpath('.//a[contains(@href,"/bar") and not(.//@style) and not (conta
   ...: ins(@href, "unwantedtext"))]/@href')
Out[7]: ['/foo/bar', '/something/bar', '/foo/bar']
Allerdings macht das ``not(.//@style)`` keinen Sinn -- kann es also sein das bei dem tatsächlichen HTML diese Bedingung dafür sorgen, dass das letzte Element nicht enthalten ist?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
LiorR91
User
Beiträge: 5
Registriert: Sonntag 1. Juli 2018, 15:43

__blackjack__ hat geschrieben: Dienstag 3. Juli 2018, 15:14 kann es also sein das bei dem tatsächlichen HTML diese Bedingung dafür sorgen, dass das letzte Element nicht enthalten ist?
Genau, ich möchte nur diejenige haben, die exakt dieses Pattern <a href="/*/bar"> treffen (also ohne weitere attributes). Vielleicht gibt es einen effizienteren Weg aber die richtige Treffer bekomme ich, nur mit der falschen Anzahl.
Also bei dem gezeigten HTML-Fragment bekomme ich das richtige raus
Merkwürdig. also ich bekomme den HTML-Text durch:

Code: Alles auswählen

    
    try:
        html_response = requests.get(url)
    except HTTPError as e:
        print(e)

    tree = html.fromstring(html_response.content)
es macht aber kein Unterschied, oder?
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Du bekommst bei dem gezeigten HTML tatsächlich nur zwei Ergebnisse? Da ist doch aber gar nichts mit einem Style-Attribut. Und bist Du sicher das Du tatsächlich ``not(.//@style)`` willst? Dir ist klar was das ``.//`` da bewirkt?

Wenn Du nur URLs willst die mit '/bar' *enden* ist `contains()` wohl auch die falsche Funktion.

Die Ausnahme”behandlung” mit `print()` ist übrigens nicht sinnvoll. Wenn da eine Ausnahme kommt, dann ist `html_response` ja nicht definiert und Du bekommst gleich danach deswegen einen `NameError`. Den Teil danach möchtest Du also vielleicht besser in einen ``else``-Zweig verschieben.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
LiorR91
User
Beiträge: 5
Registriert: Sonntag 1. Juli 2018, 15:43

__blackjack__ hat geschrieben: Dienstag 3. Juli 2018, 22:05 Du bekommst bei dem gezeigten HTML tatsächlich nur zwei Ergebnisse?
Es ist mir gerade erstmal aufgefallen dass ich gar keine Doppeltreffer im html_response habe! Krass. (Das gezeigte html war natürlich nur ein Exemplar, ich wollte kein 1000-Zeilen-HTML-Code hochladen). Ich dachte dass für identische Symbolen in einem Website bekommt man auch ein identisches html Code. Also mein Code funktioniert eigentlich. Danke für die Hilfe und sorry für meine Dummheit! :mrgreen:
Antworten