requests.get() sehr langsam.

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
Invisible90
User
Beiträge: 3
Registriert: Sonntag 1. Juli 2018, 10:14

Hey :)

ich habe mein erstes kleines Python 3 Programm fertiggestellt, allerdings tut sich ein kleines Problem auf. Der Code an sich funktioniert, allerdings benötigt requests.get() sehr lange um an den HTML Code zu kommen. Gibt es eine Möglichkeit das zu beheben? Bei dem Programm handelt es sich um einen Tellonymcrawler.

Code: Alles auswählen

import os
import requests
from bs4 import BeautifulSoup

#Clear CMD Messages
def cls():
	os.system('cls' if os.name=='nt' else 'clear')

#Calculate how many pages this profile has (Function)
def pagecount():
	pages = soup.find_all('div', {"class": "col-xs-12 text-center top-margin-1"})
	pages = pages[0].text.split(" ")
	pages = round(int(pages[6]) / 6 + 0.3)
	return pages

#Questioning and combining url
profile = input("Welches Profil moechtest du durchsuchen?\n")
word = input("Nach welchem Wort moechtest du suchen?\n")
cls()
url = "https://tellonym.me/%s" % (profile)

#Get HTML and start calculating the amount of profile pages
sauce = requests.get(url)
soup = BeautifulSoup(sauce.text, "html.parser")
pagecounter = pagecount()
tellname = soup.find_all('div', {"class": "displayname replaceEmoji"}) 

#Start scanning loop for tells with the given string
counter = 1
print(tellname[0].text.strip() + "'s Tellonym" + " | Suche nach String: " + word + "\n")
while counter <= pagecount():
	url = "https://tellonym.me/%s?page=%i" % (profile, counter) 
	sauce = requests.get(url)
	soup = BeautifulSoup(sauce.text, "html.parser")
	tellquestions = soup.find_all('div', {"class": "panel-heading tell replaceEmoji "}) 
	tellanswers = soup.find_all('div', {"class": "panel-body answer replaceEmoji "})
	telltime = soup.find_all('div', {"class": "time float-right"})
	tellcount = 0
	while tellcount < len(tellquestions):
		if word in tellquestions[tellcount].text.lower():
			found = True
			print("Frage: " + tellquestions[tellcount].text.strip())
			print("Antwort: " + tellanswers[tellcount].text.strip())
			print("Zeitraum: " + telltime[tellcount].text.strip())
			print("\n")
		tellcount += 1
	counter += 1
if not 'found' in locals():
	cls()
	print("Es wurden keine Tells mit diesem String gefunden!")
Vielen Dank für einen Tipp im Voraus. ;)
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn ich die Seite eingebe, bekomme ich ein dauerhaft laufendes Ladesymbol. Sind die vll einfach langsam?

Und generell kannst du da nichts machen. Eine Seite lädt so schnell, wie sie lädt. Du kannst bestenfalls mehrere Seiten gleichzeitig laden.
Invisible90
User
Beiträge: 3
Registriert: Sonntag 1. Juli 2018, 10:14

Danke für die schnelle Antwort.

Allerdings laden die Profile im Browser derzeit innerhalb von wenigen Millisekunden.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das mag sein, einen Weg das zu beschleunigen, der allgemein gilt, gibt es aber nicht.

Rein theoretisch könnten die requests, die nicht aus ihrer eigenen Webanwendung kommen, drosseln. Um genau das was du da treibst zu unterbinden. Ob das so ist kann man nur durch genaue Analyse bestimmen. Zb mit dem Browser Denugger, und darin dann Genau auf alle möglichen Parameter achten. Es ist allerdings immer möglich das nachzubilden.
Invisible90
User
Beiträge: 3
Registriert: Sonntag 1. Juli 2018, 10:14

Sehr schade. Wie lädt man mit requests denn mehrere Seiten aufeinmal, vielleicht wäre der Unterschied bei mehreren Seiten in der Geschwindigkeit spürbar.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Zb mit dem multiprocessing Modul. Mal nach multiprocessing und requests suchen sollte was liefern.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Invisible90: Wobei das auch nach hinten losgehen kann wenn der *eine* Server der sowieso schon drosselt, auch noch merkt das man versucht das mit mehreren Verbindungen zu umgehen. Dann sperrt der Anfragen von der IP vielleicht statt nur zu drosseln.

Und hast Du nach Erlaubnis gefragt? Denn laut deren AGB:
Wenn Sie unsere Dienste nutzen, ist es Ihnen nicht erlaubt […]:
  • Nutzerdaten oder -informationen sammelt, oder sonst in irgendeiner Weise automatisiert unseren Service nutzt (bspw. Bots, Scrapers, Spiders, Robots), ohne vorher unsere Erlaubnis einzuholen;
Bei dem Quelltext fällt die Zeile ``if not 'found' in locals():`` sofort ins Auge. Das ist überraschend/verwirrend. Setze vor der Schleife `found` auf `False` statt nach der Schleife zu schauen ob der Name existiert oder nicht, denn wenn der nach der Schleife verwendet wird, dann muss der in jedem Fall existieren, alles andere ist ein Programmierfehler.

Die beiden ``while``-Schleifen sollten eigentlich ``for``-Schleifen sein. Und die innere sollte nicht über Zahlen gehen sondern über Objekte die eine Frage/Antwort-Kombination darstellen. Das ist nämlich sehr fragil was Du da machst mit dem unabhängigen abfragen/erstellen von drei parallelen Listen und dann hoffen das die Einträge mit dem gleichen Index auch zusammen gehören. Insbesondere bei `telltime` ist es nicht unwahrscheinlich das Elemente mit den angegebenen Suchkriterien auch mal ausserhalb und vor den Fragen/Antworten kommen können und dann passt das nicht mehr. Deutlich sicherer ist eine Schleife über die Panel-Elementen und dann in der Schleife von jedem Panel Frage, Antwort, und Zeit abfragen.

Funktionen sollten alles was sie verwenden, ausser Konstanten, als Argumente übergeben bekommen. Das `pagecount()` einfach so auf `soup` zugreift, sollte nicht sein. Das innerhalb der Funktion der Name `pages` an drei total verschiedene Werte gebunden wird (Liste von Elementen, Liste von Zeichenketten, Zahl) ist verwirrend. Einen Namen innerhalb eines Namensraums möglichst immer nur für einen „duck typ“ verwenden.

Die Berechnung vom letzten `pages` ist ein wenig bizarr. Und das sieht mir mit der sehr allgemein gehaltenen Suchbedingung auch zu fragil aus. Die Anzahl der Elemente mit den CSS-Klassen `col-xs-12`, `text-center`, und `top-margin-1` ist kein robuster Weg die Anzahl von Seiten zu ermitteln. Das sollte man entweder präziser bestimmen, oder einfach mal versuchen die Seitenzahl so lange zu erhöhen bis man über die letzte Seite hinaus ist, und dann mal zu schauen was man dort dann als Abbruchkriterium verwenden könnte.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten