151 lines
6.7 KiB
Python
151 lines
6.7 KiB
Python
#!/usr/bin/env python3
|
|
|
|
"""
|
|
Dit is het 'CGI-script'.
|
|
De bestandsextensie werd aangepast om te kunnen debuggen op zowel Windows als Linux.
|
|
"""
|
|
|
|
from bs4 import BeautifulSoup
|
|
import requests
|
|
|
|
|
|
def converteer(tekst, user=True):
|
|
if user:
|
|
return tekst.replace(' ', '_')
|
|
else:
|
|
return tekst.replace('_', ' ')
|
|
|
|
|
|
def zoek_link(soep):
|
|
"""
|
|
Doorzoek de meegeleverde soep naar een geldige Wikipedia-link.
|
|
:return: een geldige link indien beschikbaar, anders None
|
|
|
|
>>> zoek_link(BeautifulSoup(requests.get('https://en.wikipedia.org/wiki/Belgium').content, 'html.parser'))
|
|
'Northwestern_Europe'
|
|
>>> zoek_link(BeautifulSoup(requests.get('https://en.wikipedia.org/wiki/Glossary_of_engineering').content, 'html.parser'))
|
|
'Glossary_of_civil_engineering'
|
|
>>> zoek_link(BeautifulSoup(requests.get('https://en.wikipedia.org/wiki/Engineering').content, 'html.parser'))
|
|
'Scientific_method'
|
|
>>> zoek_link(BeautifulSoup(requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)').content, 'html.parser'))
|
|
'High-level_programming_language'
|
|
>>> zoek_link(BeautifulSoup(requests.get('https://en.wikipedia.org/wiki/Department_of_Standards_Malaysia').content, 'html.parser'))
|
|
'Ministry_of_International_Trade_and_Industry_(Malaysia)'
|
|
"""
|
|
# TODO Zorg ervoor dat tekst schuin of vetjes ook nog herkend wordt
|
|
|
|
lijsttypes = ['ul', 'ol'] # Lijsttypes die we kunnen gebruiken
|
|
link = None
|
|
|
|
# Navigeer naar het niveau op de pagina waarop we zullen zoeken.
|
|
soep = soep.find('div', {'id': 'bodyContent'}) \
|
|
.find('div', {'class': 'mw-parser-output'})
|
|
|
|
# Niet recursief zoeken om niet in een tabel of iets dergelijke vast te komen.
|
|
# Het niveau onder 'mw-parser-output' is wat we nodig hebben en waar alle nodige alinea's in staan.
|
|
alinea = soep.find(['p', lijsttypes], recursive=False)
|
|
|
|
# Ga steeds verder omlaag (niet dieper) totdat er een geldige link is gevonden.
|
|
while link is None:
|
|
|
|
# Navigeer naar het volgende stuk tekst (alinea of lijst) met een link.
|
|
# Negeer linkjes in superscript, dus zoek enkel op het huidige niveau.
|
|
potentieel = alinea.find('a')
|
|
|
|
while potentieel is None or alinea.findChild().name == 'span':
|
|
|
|
alinea = alinea.findNextSibling(['p', lijsttypes])
|
|
|
|
# Het zou kunnen dat de bewerking hierboven ervoor zorgt dat we op het einde van de pagina zijn
|
|
if alinea is None:
|
|
return None
|
|
|
|
potentieel = alinea.find('a')
|
|
|
|
# Blijf zoeken naar linkjes in dezelfde alinea totdat deze voorwaarden voldaan zijn, maar stop van zodra er geen
|
|
# naasten meer gevonden kunnen worden.
|
|
while potentieel is not None and (
|
|
tussen_haakjes(potentieel, alinea)
|
|
# Soms kunnen hier 'interne'/externe linkjes of linkjes die niet werken (rode) tussen zitten.
|
|
or not potentieel['href'].startswith('/wiki')
|
|
or not potentieel['href'].count(':') == 0 # Bijzondere Wikipedia links negeren.
|
|
):
|
|
potentieel = potentieel.findNext('a')
|
|
|
|
if potentieel is not None:
|
|
link = potentieel['href'].split('/')[2]
|
|
|
|
return link
|
|
|
|
|
|
def tussen_haakjes(zin, omgeving):
|
|
"""
|
|
Controleer de geldigheid van de link door het aantal openende haakjes te vergelijken met het aantal sluitende
|
|
haakjes die VOOR de onderzochte link voorkomen.
|
|
Deze methode is meer waterdicht dan het vergelijken van indexen van haakjes.
|
|
Strikt genomen zou het kunnen voorkomen dat een paragraaf tussen haken staat, die we dus niet kunnen meerekenen,
|
|
maar dit voelt grammaticaal onjuist en we zullen er hier dan ook vanuit gaan dat dit niet het geval is.
|
|
|
|
>>> tussen_haakjes('woord', 'dit is een heel belangrijk woord dat we nu zoeken')
|
|
False
|
|
>>> tussen_haakjes('woord', 'dit is een (heel) belangrijk woord dat we nu zoeken')
|
|
False
|
|
>>> tussen_haakjes('woord', 'dit (is een heel belangrijk woord dat we nu) zoeken')
|
|
True
|
|
>>> tussen_haakjes('woord', 'dit (is (een heel) belangrijk woord) dat we nu zoeken')
|
|
True
|
|
"""
|
|
|
|
openende_haakjes = str(omgeving).count("(", 0, str(omgeving).find(str(zin)))
|
|
sluitende_haakjes = str(omgeving).count(")", 0, str(omgeving).find(str(zin)))
|
|
return openende_haakjes != sluitende_haakjes
|
|
|
|
|
|
def run(taal, start, stop):
|
|
"""
|
|
Paden kunnen gecontroleerd worden met https://www.xefer.com/wikipedia, al doet dit niets met 'speciale' Wikipedia-
|
|
links.
|
|
|
|
Gewone controles
|
|
>>> run('en', "Belgium", "Philosophy")
|
|
{'pad': ['Belgium', 'Northwestern Europe', 'Subregion', 'Region', 'Geography', 'Science', 'Scientific method', 'Empirical evidence', 'Proposition', 'Logic', 'Reason', 'Consciousness', 'Sentience', 'Emotion', 'Mental state', 'Mind', 'Phenomenon', 'Immanuel Kant', 'Philosophy']}
|
|
>>> run('en', 'Department of Standards Malaysia', 'Philosophy')
|
|
{'pad': ['Department_of_Standards_Malaysia', 'Ministry of International Trade and Industry (Malaysia)', 'Ministry (government department)', 'Executive (government)', 'Government', 'State (polity)', 'Germans', 'Germany', 'Central Europe', 'Europe', 'Continent', 'Landmass', 'Region', 'Geography', 'Science', 'Scientific method', 'Empirical evidence', 'Proposition', 'Logic', 'Reason', 'Consciousness', 'Sentience', 'Emotion', 'Mental state', 'Mind', 'Phenomenon', 'Immanuel Kant', 'Philosophy']}
|
|
>>> run('en', 'Malkajgiri mandal', 'Philosophy')
|
|
{'pad': ['Malkajgiri_mandal', 'Medchal%E2%80%93Malkajgiri district', 'District', 'Administrative division', 'Sovereign state', 'Polity', 'Politics', 'Decision-making', 'Psychology', 'Science', 'Scientific method', 'Empirical evidence', 'Proposition', 'Logic', 'Reason', 'Consciousness', 'Sentience', 'Emotion', 'Mental state', 'Mind', 'Phenomenon', 'Immanuel Kant', 'Philosophy']}
|
|
|
|
Loops
|
|
>>> run('nl', 'België', 'Philosophy')
|
|
|
|
Doodlopende eindes
|
|
"""
|
|
|
|
# Negeer de 'random' waarde als er op deze manier gestart wordt.
|
|
lijst = [converteer(start)] if start != 'Special:Random' else []
|
|
base = f"https://{taal}.wikipedia.org/wiki/"
|
|
|
|
while start != stop:
|
|
# Pagina inladen.
|
|
pagina = requests.get(base + start)
|
|
|
|
# Verwerken.
|
|
soep = BeautifulSoup(pagina.content, 'html.parser')
|
|
|
|
# Volgende link zoeken.
|
|
start = zoek_link(soep)
|
|
|
|
# TODO Dit verder uitwerken
|
|
if start is None:
|
|
return {'error': f'Er konden geen nieuwe links meer gevonden worden op {lijst[-1]}'}
|
|
|
|
# Cyclus detecteren
|
|
nieuw = converteer(start.split('/')[-1], False)
|
|
if nieuw in lijst:
|
|
return {
|
|
'error':
|
|
f'Cyclus gedetecteerd op {nieuw}, het onafgewerkte pad zal niet worden toegevoegd aan het overzicht'
|
|
}
|
|
|
|
lijst.append(nieuw)
|
|
|
|
return {'pad': lijst}
|