Web Crawler

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
BVB_
User
Beiträge: 5
Registriert: Donnerstag 19. Oktober 2017, 21:37

Ich versuche mich seit neustem an einen etwas komplexeren Web Crawler.
Ich nutze Python 3.6 und als Crawler BS4.

Mein Problem ist, dass ich als Ausgegeben bekomme was ich brauche.

Ich bekomme nur den Stumpfen Quelltext, ich brauche jedoch den Quelltext den Ich auch mit dem Firefox "Element Untersuchen" Funktion ausgegeben bekomme.
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

du müsstest halt mal deine Code zeigen. Ohne kann man nicht viel sagen.

Grundsätzlich lädt ein Webcrawler in der Tat nur den "stumpfen Quelltext". Elemente, die später z.B. über JavaScript dynamisch hinzugefügt werden, bekommst du so nicht.

Gruß, noisefloor

P.S.: Willkommen im Forum :-)
BVB_
User
Beiträge: 5
Registriert: Donnerstag 19. Oktober 2017, 21:37

Mein Problem ist, dass ich als Ausgegeben bekomme was ich brauche.
Korrektur : Mein Problem ist, dass ich nicht das ausgegeben bekomme was ich will.


Mein Code:

Code: Alles auswählen

from bs4 import BeautifulSoup
from urllib.request import Request, urlopen

my_url = 'https://de.tonybet.com/event/1364763'

webpage = Request(my_url, headers={'User-Agent': 'Mozilla/5.0'})
page_html = urlopen(webpage).read()

soup = BeautifulSoup(page_html, 'lxml')

sou_aus1 = soup.find_all("data-event-odd-id")

print(sou_aus1)
Ich habe nun erfahren das ich nicht die HTML sondern den DOM auslesen will.
Habe das Wort lxml damit oft in Verbindung gelesen, stehe aber derzeit noch auf den schlauch.
P.S.: Willkommen im Forum :-)
Danke ;)
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Habe das Wort lxml damit oft in Verbindung gelesen, stehe aber derzeit noch auf den schlauch.
lxml ist ein XML/HTML Parser. Der kommt aber auch nicht an den Inhalt des DOM.

Ein gängiger Weg ist der Einsatz von Selenium. Damit kommst du auch an den Inhalt des DOM.

Gruß, noisefloor
Benutzeravatar
pixewakb
User
Beiträge: 1408
Registriert: Sonntag 24. April 2011, 19:43

Mir gefällt die folgende Zeile nicht:

Code: Alles auswählen

sou_aus1 = soup.find_all("data-event-odd-id")
Ich würde eher so etwas erwarten:

Code: Alles auswählen

content = soup.find_all("div", attr={"class": "data-event-odd-id"})
Du solltest Dir mal das Modul requests ansehen. Das ist sehr viel einfacher zu nutzen, als die urllib.request-Sache. Auf Selenium wurdest Du bereits hingewiesen.
BVB_
User
Beiträge: 5
Registriert: Donnerstag 19. Oktober 2017, 21:37

Du solltest Dir mal das Modul requests ansehen. Das ist sehr viel einfacher zu nutzen, als die urllib.request-Sache. Auf Selenium wurdest Du bereits hingewiesen.
Die urllib ist erst mal nicht mehr nötig dank Selenium, aber ich werde es mir später anschauen.

Ich habe jetzt die gewünschten Ausschnitte von der DOM filtern können.

https://pastebin.com/SjFJ3EWJ /Teil Ausgabe

Ich will jetzt die Ausgabe nun so ausgegeben bekommen

Bester Punktestand
Die meisten Treffer im ersten Viertel: 3.40
Die meisten Treffer im 2. Viertel: 4.0
Die meisten Treffer im 3. Viertel: 3.75
....

BeautifulSoup kann ich nicht wieder anwenden, bekomme da ein Fehler und eine andere Lösung kenne ich für meine Wunschausgabe nicht.

Mein Code

Code: Alles auswählen

from selenium import webdriver
from bs4 import BeautifulSoup

browser = webdriver.Chrome('C:\\chromedriver.exe')
browser.get("https://de.tonybet.com/event/1372234")
page_dom = browser.page_source

soup = BeautifulSoup(page_dom, 'lxml')

bet_content = soup.find_all("div", attrs={"class":"panel panel-gray panel-odds"})
bet_content_len = len(bet_content)
print(bet_content_len)

for bet in bet_content:
    print(bet)
BVB_
User
Beiträge: 5
Registriert: Donnerstag 19. Oktober 2017, 21:37

Ich kann mein Beitrag nicht bearbeiten, deshalb der neue Post.

Das was ich seit 8 Stunden probiere geht plötzlich, brauche erst mal keine Hilfe :)
Benutzeravatar
pixewakb
User
Beiträge: 1408
Registriert: Sonntag 24. April 2011, 19:43

Du kannst "lauffähigen" Code gerne auch hier posten, möglicherweise hilft er anderen...
FlexingFlo
User
Beiträge: 1
Registriert: Freitag 5. Januar 2018, 14:26

# Importieren der Funktionen aus BeautifulSoup
from urllib.request import urlopen as uReq
from bs4 import BeautifulSoup as soup, Tag
import bs4


Interne_Links = [] #Listen, um Links geordnet zu speichern.
Links = []
usedurl = []
startpage = "https://justiz.de/bundlaender/bund/index.php" # Url welche gescrapet werden soll.
url = "https://justiz.de" # Basis url die nachher mit den seiteninternen Links "addiert" wird, um vollständige Links zu erhalten.



def Linkfinder(page):
uClient = uReq(page) # Web scraping : Seite öffnen,download, Verbindung trennen.
page_html = uClient.read()
uClient.close


page_soup = soup(page_html,"html.parser") # Bs4 anwenden, um Seite durchsuchen zu können.

# Verarbeitung
containers = page_soup.findAll("a") # Alle "a Tags" (html) finden.
for item in containers: # Für jeden html Tag (fals vorhanden) den href greifen.
link = item.get('href')
if link != None and not "@" in link:: # Wenn ein href vorhanden ist, kein none zurückgegeben wurde, entwerder :
if link[0:5] == "../.." : # 1. wenn die ersten 5 Zeichen des href "../.." sein sollten, diese enfernen,
# und mit der basis url "addieren", um diese ,der liste "Interne_Links", hinzufügen.


Interne_Links.append(url+link[5:])
else:
Links.append(link) # 2. Wenn die ersten Zeichen den Links NICHT "../.." sein sollten, wird dieser der Liste "Links" hinzufügen
usedurl.append(page)





Linkfinder(startpage)
for page in Interne_Links:
if not page in usedurl:
Linkfinder(page)
# Ausgabe
print("Links")
print(Links)
print(20*"-")
print("Seiten interne Links")
print(Interne_Links)


Ich hätte eine Frage an euch erfahrene Programmierer:
Wie kann ich in den Linkfinder einbauen, dass dieser in die tiefe geht. Also als Beispiel: Das Programm holt sich einen Link aus einer Seite, und geht diesen Links drei nach. Danach hört er auf. Damit man kein ewiges Monster erschafft.

Hoffe ihr habt die Beschreibung verstanden :roll:, wenn nicht fragt einfach nach :D :shock:
Benutzeravatar
pixewakb
User
Beiträge: 1408
Registriert: Sonntag 24. April 2011, 19:43

Pep8 beachten, bitte Codebox für den Code verwenden und zu deiner letzten Frage: Ich würde prüfen, ob die Links zur Seite gehören oder auf eine externe Seite verweisen. Wenn du dann besuchte Seiten nachhältst, kannst du sicher gehen, dass du die komplette Seite erfasst - kann halt nach Umfang etwas dauern...
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dein Code ist ohne Code-Tags leider nicht wirklich lesbar.

Vom Prinzip ist das Problem aber einfach zu loesen: du merkst dir fuer jeden Link nicht nur dessen URL, sondern auch seine Tiefe. In einer gecrawlten Seite, die neue Links enthaelt, merkst du dir die mit aktueller Tiefe + 1. Und wenn ein Link mit einer Tiefe groesser als die vorgesehene besucht werden soll, machst du nix.

Oder du benutzt einfach wget, was so etwas schon kann.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

BS4 ist kein Crawler. Wenn du das Rad nicht neu erfinden willst, nimm Scrapy. Damit kannst du dich dann aufs wesentlich konzentrieren. Wenn du Seiten die JS nutzen crawlen willst, versuch direkt die APIs zu nutzen die der JS code nutzt, ansonsten ist es schwierig einen stabilen Crawler zu schreiben. Wenn dies aus irgendeinem Grund nicht funktioniert hat Scrapy mit scrapy-splash auch hierfür eine Lösung.
Antworten