Sådan oprettes en URL-crawler til at kortlægge et websted ved hjælp af Python

Et simpelt projekt til at lære de grundlæggende aspekter af webskrabning

Lad os sørge for, at vi forstår, hvad webskrabning er, inden vi starter:

Webskrabning er processen med at udtrække data fra websteder for at præsentere det i et format, som brugere let kan give mening om.

I denne vejledning vil jeg demonstrere, hvor let det er at oprette en simpel URL-crawler i Python, som du kan bruge til at kortlægge websteder. Mens dette program er relativt simpelt, kan det give en god introduktion til det grundlæggende inden for webskrabning og automatisering. Vi vil fokusere på rekursivt at udvinde links fra websider, men de samme ideer kan anvendes på et utal af andre løsninger.

Vores program fungerer således:

  1. Besøg en webside
  2. Skrab alle unikke URL'er, der findes på websiden, og tilføj dem til en kø
  3. Behandl webadresser rekursivt en efter en, indtil vi udtømmer køen
  4. Udskriv resultater

Første ting først

Den første ting, vi skal gøre, er at importere alle de nødvendige biblioteker. Vi bruger BeautifulSoup, anmodninger og urllib til webskrabning.

from bs4 import BeautifulSoupimport requestsimport requests.exceptionsfrom urllib.parse import urlsplitfrom urllib.parse import urlparsefrom collections import deque

Dernæst skal vi vælge en URL til at begynde at gennemgå. Mens du kan vælge en hvilken som helst webside med HTML-links, anbefaler jeg at bruge ScrapeThisSite. Det er en sikker sandkasse, som du kan kravle uden at komme i problemer.

url = “//scrapethissite.com”

Derefter bliver vi nødt til at oprette et nyt deque-objekt, så vi let kan tilføje nyligt fundne links og fjerne dem, når vi er færdige med at behandle dem. Forudfyld befolkningen med din urlvariabel:

# a queue of urls to be crawled nextnew_urls = deque([url])

Vi kan derefter bruge et sæt til at gemme unikke URL'er, når de er blevet behandlet:

# a set of urls that we have already processed processed_urls = set()

Vi vil også holde styr på lokalt (samme domæne som målet), fremmed (andet domæne som målet) og ødelagte webadresser:

# a set of domains inside the target websitelocal_urls = set()
# a set of domains outside the target websiteforeign_urls = set()
# a set of broken urlsbroken_urls = set()

Tid til at kravle

Med alt det på plads kan vi nu begynde at skrive den faktiske kode for at gennemgå webstedet.

Vi vil se på hver URL i køen, se om der er yderligere URL'er inden for den side og tilføj hver enkelt til slutningen af ​​køen, indtil der ikke er nogen tilbage. Så snart vi er færdige med at skrabe en URL, fjerner vi den fra køen og føjer den til processed_urlssættet til senere brug.

# process urls one by one until we exhaust the queuewhile len(new_urls): # move url from the queue to processed url set url = new_urls.popleft() processed_urls.add(url) # print the current url print(“Processing %s” % url)

Dernæst tilføj en undtagelse for at fange eventuelle ødelagte websider og tilføj dem til broken_urlssættet til senere brug:

try: response = requests.get(url)
except(requests.exceptions.MissingSchema, requests.exceptions.ConnectionError, requests.exceptions.InvalidURL, requests.exceptions.InvalidSchema): # add broken urls to it’s own set, then continue broken_urls.add(url) continue

Vi har derefter brug for at få basiswebadressen på websiden, så vi let kan differentiere lokale og udenlandske adresser:

# extract base url to resolve relative linksparts = urlsplit(url)base = “{0.netloc}”.format(parts)strip_base = base.replace(“www.”, “”)base_url = “{0.scheme}://{0.netloc}”.format(parts)path = url[:url.rfind(‘/’)+1] if ‘/’ in parts.path else url

Initialiser BeautifulSoup for at behandle HTML-dokumentet:

soup = BeautifulSoup(response.text, “lxml”)

Skrab nu websiden for alle links, og sorter dem, føj dem til deres tilsvarende sæt:

for link in soup.find_all(‘a’): # extract link url from the anchor anchor = link.attrs[“href”] if “href” in link.attrs else ‘’
if anchor.startswith(‘/’): local_link = base_url + anchor local_urls.add(local_link) elif strip_base in anchor: local_urls.add(anchor) elif not anchor.startswith(‘http’): local_link = path + anchor local_urls.add(local_link) else: foreign_urls.add(anchor)

Da jeg kun vil begrænse min webcrawler til lokale adresser, tilføjer jeg følgende for at tilføje nye webadresser til vores kø:

for i in local_urls: if not i in new_urls and not i in processed_urls: new_urls.append(i)

Hvis du vil gennemgå alle webadresser, skal du bruge:

if not link in new_urls and not link in processed_urls: new_urls.append(link)

Advarsel: Den måde, programmet i øjeblikket fungerer på, gennemgår udenlandske webadresser meget lang tid. Du kan muligvis komme i problemer med at skrabe websteder uden tilladelse. Brug på egen risiko!

Her er al min kode:

Og det skulle være det. Du har lige oprettet et simpelt værktøj til at gennemgå et websted og kortlægge alle fundne webadresser!

Afslutningsvis

Du er velkommen til at bygge videre på og forbedre denne kode. For eksempel kan du ændre programmet til at søge på websider efter e-mail-adresser eller telefonnumre, når du gennemsøger dem. Du kan endda udvide funktionaliteten ved at tilføje kommandolinjeargumenter for at give mulighed for at definere outputfiler, begrænse søgninger til dybde og meget mere. Lær om, hvordan du opretter kommandolinjegrænseflader til at acceptere argumenter her.

Hvis du har yderligere anbefalinger, tip eller ressourcer, bedes du dele i kommentarerne!

Tak for læsningen! Hvis du kunne lide denne tutorial og vil have mere indhold som dette, skal du sørge for at knuse den følgende knap. ❤️

Sørg også for at tjekke min hjemmeside, Twitter, LinkedIn og Github.