Parser bricht nach 20 Zeilen einfach ab..

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
Benutzeravatar
say_hello
User
Beiträge: 51
Registriert: Sonntag 14. Oktober 2012, 12:33

Guten Abend Community,

bei dem Parser bricht das Auswerten der Daten nach 20 Records ab.

Was ist beabsichtigt: ... die Pages der Volunteering-Angebote zu sammeln u. parsen und als CSV zu speichern.

m.a.W:

- https://europa.eu/youth/volunteering/organisation/50188
- https://europa.eu/youth/volunteering/organisation/50190

und so weiter und so fort: es gibt mor als 6000 records - doch der Parser bricht nach 20 Zeilen ab: m.a.W. es gibt eine CSV-Ausgabe mit nur 20 Zeilen...


der Zugang :

Code: Alles auswählen


import requests
from bs4 import BeautifulSoup
import re
import csv
from tqdm import tqdm


first = "https://europa.eu/youth/volunteering/organisations_en?page={}"
second = "https://europa.eu/youth/volunteering/organisation/{}_en"


def catch(url):
    with requests.Session() as req:
        pages = []
        print("Loading All IDS\n")
        for item in tqdm(range(0, 347)):
            r = req.get(url.format(item))
            soup = BeautifulSoup(r.content, 'html.parser')
            numbers = [item.get("href").split("/")[-1].split("_")[0] for item in soup.findAll(
                "a", href=re.compile("^/youth/volunteering/organisation/"), class_="btn btn-default")]
            pages.append(numbers)
        return numbers


def parse(url):
    links = catch(first)
    with requests.Session() as req:
        with open("Data.csv", 'w', newline="", encoding="UTF-8") as f:
            writer = csv.writer(f)
            writer.writerow(["Name", "Address", "Site", "Phone",
                             "Description", "Scope", "Rec", "Send", "PIC", "OID", "Topic"])
            print("\nParsing Now... \n")
            for link in tqdm(links):
                r = req.get(url.format(link))
                soup = BeautifulSoup(r.content, 'html.parser')
                task = soup.find("section", class_="col-sm-12").contents
                name = task[1].text
                add = task[3].find(
                    "i", class_="fa fa-location-arrow fa-lg").parent.text.strip()
                try:
                    site = task[3].find("a", class_="link-default").get("href")
                except:
                    site = "N/A"
                try:
                    phone = task[3].find(
                        "i", class_="fa fa-phone").next_element.strip()
                except:
                    phone = "N/A"
                desc = task[3].find(
                    "h3", class_="eyp-project-heading underline").find_next("p").text
                scope = task[3].findAll("span", class_="pull-right")[1].text
                rec = task[3].select("tbody td")[1].text
                send = task[3].select("tbody td")[-1].text
                pic = task[3].select(
                    "span.vertical-space")[0].text.split(" ")[1]
                oid = task[3].select(
                    "span.vertical-space")[-1].text.split(" ")[1]
                topic = [item.next_element.strip() for item in task[3].select(
                    "i.fa.fa-check.fa-lg")]
                writer.writerow([name, add, site, phone, desc,
                                 scope, rec, send, pic, oid, "".join(topic)])


parse(second)


Aber nach dem Parsen von nur 20 Zeilen bricht alles ab. :: es gibt also eine CSV-Ausgabe mit nur 20 Zeilen..
Ich denke dass ich am Ende der ersten Funktion auch eher Pages als numbers zurückgeben sollte.

Code: Alles auswählen

   pages.append(numbers)
        return numbers
 
Also ich denke dass da ein Fehler drinne ist. Aber irgendwie komme ich nicht weiter.


Was meint Ihr denn!?
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Was heißt denn "bricht ab"? Gibt es eine Fehlermeldung?

Wenn es 20 requests lang geht und beim 21 nicht mehr, musst du heraufidnen, was beim 21 anders ist. Und ob auf der Seite noch das ist, was du erwartest. Es kann auch durchaus sein, dass der Anbieter die Zugriffe beschränkt.
Benutzeravatar
say_hello
User
Beiträge: 51
Registriert: Sonntag 14. Oktober 2012, 12:33

hallo Sparrow,

vielen Dank für Deine Rückmeldung.

Die Startseite ist diese hier: https://europa.eu/youth/volunteering/organisations_en

Die erste Funktion catch loopt von 0 to 3xy Seiten, jede Seite gibt 20 id, so 20 * 3xy = 6xxx Resultate

Ich werde nochmals genauer nachsehen, was an der 21. Zeile anders ist - bzw. warum geanu nur eine einzige Seite gewissermaßen ausgewertet wird - geholt werden aber alle Seiten - das ist das Interessante.

Dir nochmals vielen Dank für Deine Rückmeldung und deinen Hinweis. Ich werde mich nochmals darum kümmern.


VG Say_hello
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Ohne jetzt deinen Code tief angeschaut zu haben:
Wenn du von einer Seite 20 Einträge holst und das funktioniert, dann geht wohl etwas schief, wenn du die Seite mit den nächsten 20 Einträgen holst. Falls du das tust.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum denkst Du nur, dass in der ersten Funktion ein Fehler ist? Warum weißt Du das nicht?
Funktionen schreibt man ja nicht und hofft dann, das sie richtig funktionieren, sondern testet sie, z.B. indem man mal ausgeben läßt, was in den Variablen so drinsteht.
findAll ist veraltet, statt dessen benutzt man find_all. Warum schneidest Du aus den URLs die Nummer heraus, wenn Du später daraus wieder eine URL zusammenbaust? Nimm doch gleich die kompletten URLs. Die hart codierten 347 sind schlecht, such doch einfach den Next-Button auf jeder Seite.
Warum nennst Du eine Session req?
Benutzeravatar
say_hello
User
Beiträge: 51
Registriert: Sonntag 14. Oktober 2012, 12:33

hallo und guten Abend Sparrow und Sirius3

vielen Dank für Eure Rückmeldungen und die Tipps - alle insges. nachvollziehbar - klar - hartcodierte Seitennummmern sind dann ungünstig wenn sich die Menge der Daten ändert.

Ich gehe alles nochmals durch. Euch vielen Dank für die Tipps

Viele Grüße


update:
ich werde weitere Tests durchführen. ..

Code: Alles auswählen


runfile('/home/martin/dev/may_13__eu_volun.py', wdir='/home/martin/dev')
  0%|          | 0/347 [00:00<?, ?it/s]Loading All IDS

100%|██████████| 347/347 [02:16<00:00,  2.54it/s]
  0%|          | 0/20 [00:00<?, ?it/s]
Parsing Now... 

100%|██████████| 20/20 [00:19<00:00,  1.03it/s]

Zuletzt geändert von say_hello am Donnerstag 13. Mai 2021, 22:21, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Also das wäre mal ein Anfang:

Code: Alles auswählen

import urllib
import requests
from bs4 import BeautifulSoup


ORGANISATIONS_URL = "https://europa.eu/youth/volunteering/organisations_en"

def fetch_all_urls(url):
    with requests.Session() as session:
        while True:
            response = session.get(url)
            soup = BeautifulSoup(response.content, 'html.parser')
            for item in soup.select('div.eyp-card a.btn'):
                yield urllib.parse.urljoin(url, item['href'])
            next = soup.select_one('li.next a')
            if next is None:
                break
            url = urllib.parse.urljoin(url, next['href'])


for url in fetch_all_urls(ORGANISATIONS_URL):
    print(url)
Benutzeravatar
say_hello
User
Beiträge: 51
Registriert: Sonntag 14. Oktober 2012, 12:33

Hallo Sirius,

vielen Dank - das bringt uns um die hardcoded Variante - das ganze fest auf eine bestimmte Anzahl von Seiten festzulegen herum.

Code: Alles auswählen

https://europa.eu/youth/volunteering/organisation/49252_en
https://europa.eu/youth/volunteering/organisation/51855_en
https://europa.eu/youth/volunteering/organisation/59469_en
https://europa.eu/youth/volunteering/organisation/49520_en
https://europa.eu/youth/volunteering/organisation/62482_en
https://europa.eu/youth/volunteering/organisation/50438_en
und schon sind wir in der Lage flexibel die Seiten zu holen.


ich guck mal wie wir das dann parsen


- Vielen Dank Dir jedenfalls bis hierher.


Viele Grüße :)
Antworten