String-Operation

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.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Eine gute Quelle für Tips und Tricks rund um Pandas bietet Kevin Markham auf seinem Youtube Channel https://www.youtube.com/user/dataschool/videos und auf Twitter.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
Strawk
User
Beiträge: 229
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo Sirius3!
Dein Code vom 16.08.2019, 22.34 Uhr funktioniert insoweit nicht, als die Fehlermeldung kommt:
Zeile 32: TypeError: list indices must be integers or slices, not str
Ich würde deinen Code aber gerne weiterverwenden, da er wohl kürzer und besser ist.
Grüße
Strawk
Ich programmiere erfolglos, also bin ich nicht.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Zeile 32 ist das wohl ehere nicht (das nächste mal bitte den kompletten Traceback, damit ich nicht raten muß). Wahrscheinlich muß es einfach anchor[0] heißen, wenn man annimmt, dass in jeder Tabellenzelle nur jeweils ein <a> vorkommt.
Benutzeravatar
Strawk
User
Beiträge: 229
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Mit anchor[0] dort ergibt sich das Folgende:

runfile('C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx/TorSiteCompleteInfo.py', wdir='C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx')
Reloaded modules: geo_mk, geo_mk.geo_gpx, geo_mk.geo_distances, geo_mk.geo_utils, geo_mk.geo_visualization
Traceback (most recent call last):

File "<ipython-input-4-04c4a6166c3e>", line 1, in <module>
runfile('C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx/TorSiteCompleteInfo.py', wdir='C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx')

File "C:\Users\Karl Kraft\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
execfile(filename, namespace)

File "C:\Users\Karl Kraft\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)

File "C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx/TorSiteCompleteInfo.py", line 46, in <module>
main()

File "C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx/TorSiteCompleteInfo.py", line 39, in main
locations = read_locations(url="https://torstatus.blutmagie.de/")

File "C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx/TorSiteCompleteInfo.py", line 32, in read_locations
query = dict(parse_qsl(urlparse(anchor[0]).query))

File "C:\Users\Karl Kraft\Anaconda3\lib\urllib\parse.py", line 367, in urlparse
url, scheme, _coerce_result = _coerce_args(url, scheme)

File "C:\Users\Karl Kraft\Anaconda3\lib\urllib\parse.py", line 123, in _coerce_args
return _decode_args(args) + (_encode_result,)

File "C:\Users\Karl Kraft\Anaconda3\lib\urllib\parse.py", line 107, in _decode_args
return tuple(x.decode(encoding, errors) if x else '' for x in args)

File "C:\Users\Karl Kraft\Anaconda3\lib\urllib\parse.py", line 107, in <genexpr>
return tuple(x.decode(encoding, errors) if x else '' for x in args)

File "C:\Users\Karl Kraft\Anaconda3\lib\site-packages\bs4\element.py", line 1173, in decode
indent_space = (' ' * (indent_level - 1))

TypeError: unsupported operand type(s) for -: 'str' and 'int'

Grüße, S.
Ich programmiere erfolglos, also bin ich nicht.
Benutzeravatar
Strawk
User
Beiträge: 229
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hier noch der Traceback von: anchor['href']

runfile('C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx/TorSiteCompleteInfo.py', wdir='C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx')
Reloaded modules: geo_mk, geo_mk.geo_gpx, geo_mk.geo_distances, geo_mk.geo_utils, geo_mk.geo_visualization
Traceback (most recent call last):

File "<ipython-input-5-04c4a6166c3e>", line 1, in <module>
runfile('C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx/TorSiteCompleteInfo.py', wdir='C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx')

File "C:\Users\Karl Kraft\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
execfile(filename, namespace)

File "C:\Users\Karl Kraft\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)

File "C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx/TorSiteCompleteInfo.py", line 46, in <module>
main()

File "C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx/TorSiteCompleteInfo.py", line 39, in main
locations = read_locations(url="https://torstatus.blutmagie.de/")

File "C:/Users/Karl Kraft/Documents/Programmierung_ausser_PHP/Python/gpx/TorSiteCompleteInfo.py", line 32, in read_locations
query = dict(parse_qsl(urlparse(anchor['href']).query))

TypeError: list indices must be integers or slices, not str

Gruß, Strawk
Ich programmiere erfolglos, also bin ich nicht.
Benutzeravatar
Strawk
User
Beiträge: 229
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo!
Ich bin jetzt wieder bei den regulären Ausdrücken. Anders lassen sich nicht alle Informationen aus der Tabelle scrapen.
Bitte betrachtet folgenden String:

Code: Alles auswählen

<tr class='r'>
<td class='TRr'>
<a href='http://www.openstreetmap.org/?mlon=9.4910&mlat=51.2993&zoom=6' target='_blank'><img src='img/flags/de.gif' class='flag' width='18px' title='//DE' alt='DE' border='0'></a>
&nbsp;
<a href='router_detail.php?FP=749ef4a434dfd00dab31e93de86233fb916d31e3' target='_blank'>ExitNinja</a></td>
<td class='TDb'>
<table cellspacing='0' cellpadding='0' class='bwb'>
<tr title='57259 KBs'><td class='bwr5'><img src='img/bar/9.png' width='12px' height='15px' alt='57259'></td><td>&nbsp;<small>&nbsp;57259</small></td></tr>
</table>
</td>

<td class='TDcb'>33 d</td>
<td class='TDS'>
<table class='iT'>
<tr><td class='iT'>46.165.245.154 [<a class='who' href='/cgi-bin/whois.pl?ip=46.165.245.154' target='_blank'>46.165.245.154</a>]</td>
<td><img src='img/status/Fast.png' title='Fast Server' alt='Fast Server'></td>
<td><img src='img/status/Exit.png' title='Exit Server' alt='Exit Server'></td>
<td><img src='img/status/Dir.png' title='Directory Server' alt='Directory Server'></td>
<td><img src='img/status/Guard.png' title='Guard Server' alt='Guard Server'></td>
<td><img src='img/status/Stable.png' title='Stable Server' alt='Stable Server'></td>
<td><img src='img/os-icons/Linux.png' title='Tor 0.4.0.5 on Linux' alt='Tor 0.4.0.5 on Linux'></td>
</tr>
</table>
</td>
<td class='TDc'><b>443</b></td>
<td class='TDc'><b>80</b></td>
<td class='F0'></td>
<td class='TDS'>2014-11-06&nbsp;</td>
<td class='TDS'>LEASEWEB-DE-FRA-10, DE&nbsp;</td>
<td class='TDS'>28753&nbsp;</td>
<td class='TDc'>120000&nbsp;</td>
<td class='TDS'>&nbsp;</td>
</tr>
Ich bastele gerade an einem regulären Ausdruck, der mir den Routernamen liefert (hier: ExitNinja). Wie muss der wohl lauten?
Grüße
Strawk

P.S.: So jedenfalls nicht:

Code: Alles auswählen

result_rounter_name = re.search(r"target[=]*'[_]*blank'&gt;[a-zA-Z0-9]{3,30}&lt;[/]*a&gt;&lt;[/]*td&gt;", table_row)
Ich programmiere erfolglos, also bin ich nicht.
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Strawk: Reguläre Ausdrücke sind nicht geeignet HTML zu parsen. Und natürlich geht das auch ohne regulären Ausdruck und zwar *einfach*, denn das ist ja einfach der Textinhalt vom zweiten <a> in der Tabellenzelle. Da kommt man mit Beautifulsoup wesentlich einfacher und verständlicher heran als der Ausdruck den Du da jetzt schon verbrochen hast.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Strawk: ich will Dir hier nicht jeden simplen Fehler, den man schnell durch Debugging beheben könnte, lösen. Wenn man nicht weiß, warum z.B. ein Index nicht richtig ist, dann gibt man einfach vor der Stelle die betroffenen Variablen aus und sieht ganz schnell dass find_all natürlich eine Liste von HTML-Objekten zurückliefert, man also (da an der Stelle wohl nur eines möglich ist) auf das 0te-Element zugreifen muß, um dann EIN HTML-Objekt zu haben, von dem man dann das href-Attribut abfragen kann.
Benutzeravatar
Strawk
User
Beiträge: 229
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

@Sirius3: Dass anchor[0] nicht funktioniert, so weit waren wir schon. Es ist nunmal des einen Spaziergang des anderen Gewaltmarsch und ich bitte um Übermittlung des funktionierenden Klarcodes! Danke. Grüße, S. (Seit Wochen am Basteln, da kann einem doch mal kurzfristig auf die Sprünge geholfen werden; es ist ja nicht so, dass ich mir keine Mühe gäbe oder das Programmieren-Lernen mit lieferando verwechselte.)
Ich programmiere erfolglos, also bin ich nicht.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Du solltest den Code auseinandernehmen und debuggen, wie man das nun macht, wenn ein Programm nicht funktioniert.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Also den Routernamen kann man so ermitteln:

Code: Alles auswählen

from bs4 import BeautifulSoup
from io import StringIO
import re

TEST_STREAM = StringIO("""\
<tr class='r'>
<td class='TRr'>
<a href='http://www.openstreetmap.org/?mlon=9.4910&mlat=51.2993&zoom=6' target='_blank'><img src='img/flags/de.gif' class='flag' width='18px' title='//DE' alt='DE' border='0'></a>
&nbsp;
<a href='router_detail.php?FP=749ef4a434dfd00dab31e93de86233fb916d31e3' target='_blank'>ExitNinja</a></td>
<td class='TDb'>
<table cellspacing='0' cellpadding='0' class='bwb'>
<tr title='57259 KBs'><td class='bwr5'><img src='img/bar/9.png' width='12px' height='15px' alt='57259'></td><td>&nbsp;<small>&nbsp;57259</small></td></tr>
</table>
</td>

<td class='TDcb'>33 d</td>
<td class='TDS'>
<table class='iT'>
<tr><td class='iT'>46.165.245.154 [<a class='who' href='/cgi-bin/whois.pl?ip=46.165.245.154' target='_blank'>46.165.245.154</a>]</td>
<td><img src='img/status/Fast.png' title='Fast Server' alt='Fast Server'></td>
<td><img src='img/status/Exit.png' title='Exit Server' alt='Exit Server'></td>
<td><img src='img/status/Dir.png' title='Directory Server' alt='Directory Server'></td>
<td><img src='img/status/Guard.png' title='Guard Server' alt='Guard Server'></td>
<td><img src='img/status/Stable.png' title='Stable Server' alt='Stable Server'></td>
<td><img src='img/os-icons/Linux.png' title='Tor 0.4.0.5 on Linux' alt='Tor 0.4.0.5 on Linux'></td>
</tr>
</table>
</td>
<td class='TDc'><b>443</b></td>
<td class='TDc'><b>80</b></td>
<td class='F0'></td>
<td class='TDS'>2014-11-06&nbsp;</td>
<td class='TDS'>LEASEWEB-DE-FRA-10, DE&nbsp;</td>
<td class='TDS'>28753&nbsp;</td>
<td class='TDc'>120000&nbsp;</td>
<td class='TDS'>&nbsp;</td>
</tr>""")

def get_router_name(soup):
    pattern = re.compile(r'router_detail.*')
    match = soup.find('a', href=pattern)
    if not match:
        raise ValueError('Missing router_detail link')
    return match.text

def main():
    soup = BeautifulSoup(TEST_STREAM)
    print(get_router_name(soup))

if __name__ == '__main__':
    main()
Anstelle von TEST_STREAM muss man natürlich den Stream von urlopen() oder requests einsetzen.
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@snafu: Kann man natürlich so machen, aber das ist eine Tabelle in der die Zeilen immer so aufgebaut sind, dass in der ersten Zelle erst ein Link zu OpenStreetMap ist (wo die latitude/longitude-Informationen drin stecken die vorher hier Thema waren), und dann der Routername.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Strawk hat geschrieben: Donnerstag 22. August 2019, 14:21 Es ist nunmal des einen Spaziergang des anderen Gewaltmarsch
Allerdings. Ich hatte halt noch in Erinnerung, dass BeautifulSoup reguläre Ausdrücke beherrscht, aber ich wusste nicht mehr genau, wie man vorgehen muss. Also Google angeschmissen und nach "beautifulsoup href regex" gesucht und dann war der Rest schnell runtergetippt und funktionierte auch gleich beim ersten Durchlauf.

Neben einer gewissen Erfahrung, logischem Denken und dem ganzen anderen "Programmier-Kram" gehört zu einer erfolgreichen Lösung eben auch einfach die Fähigkeit, eine Suchmaschine vernünftig zu bedienen. Dann stößt man meist auf Doku oder auf Beispiele von StackOverflow. Gerade so triviale Sachen kosten einen dann vielleicht 5 Minuten Lebenszeit...
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@__blackjack__: Ich hab hier ehrlich gesagt nur die letzten Beiträge gelesen. Wenn man sich auf eine fixe Position verlassen kann, dann ginge natürlich auch ein entsprechender Indexzugriff.
Benutzeravatar
Strawk
User
Beiträge: 229
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo Nutzer!
Nach Refaktorierung des Skripts braucht es nun 115 Sekunden, anstatt 42. Ich habe versucht, mit einem zeilenweise Profiler zu arbeiten. Der Befehl
python -m line_profiler scrapeTor.py.lprof > results.txt
generiert auch tatsächlich das Skript results.txt. Dessen einziger Eintrag ist jedoch
Timer unit: 3.20721e-07 s
.
Warum fehlen die Zeitinfos?
Grüße
Strawk
Ich programmiere erfolglos, also bin ich nicht.
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Strawk: Vielleicht weil das nix ausgeführt wird weil ``scrapeTor.py.lprof`` sehr wahrscheinlich nicht der Name des Programms ist‽
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
Strawk
User
Beiträge: 229
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Doch. So lautet der Befehl. Erst:
kernprof -l scrapeTor.py
dann:
python -m line_profiler scrapeTor.py.lprof > results.txt
Mein Skript heißt scrapeTor.py
Ich programmiere erfolglos, also bin ich nicht.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Hast Du die Funktion, die Du profilieren willst, auch markiert?
Benutzeravatar
Strawk
User
Beiträge: 229
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Ich habe nichts markiert. Ich möchte das gesamte Skript auf seine Zeiten hin überprüfen.
Ich programmiere erfolglos, also bin ich nicht.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Strawk: es hilft immer, die Dokumentation zu lesen, bevor man etwas benutzt:
It has been written to be used as a decorator, so in your script, you decorate the functions you want to profile with @profile.

Code: Alles auswählen

@profile
def slow_function(a, b, c):
Antworten