Gebruiker:Wikiwernerbot/internet archive.py

Uit Wikipedia, de vrije encyclopedie
import pywikibot
import re
import requests
import datetime
site = pywikibot.Site()

archiveorgre = re.compile(r'http://web\.archive\.org/[^"]*')
bezochtdatumre = re.compile(r'(bezochtdatum|access-?date|datumbezocht|datumgeraadpleegd|raadpleegdatum)\s*=\s*(.*?)\s*[|}]')
citeerstartre = re.compile(r'\{\{\s*([Cc]ite(er)? [a-z]|[Vv]oetnoot web)')
geraadpleegdre = re.compile(r'(eraadpleegd|pgevraagd) (op )?(.*?)[.\s]*</ref>')
datumre1 = re.compile(r'^\d{4}-\d\d?-\d\d?$')
datumre2 = re.compile(r'^\d\d?-\d\d?-\d{4}$')
datumre3 = re.compile(r'^\d\d? [A-Za-z]+ \d{4}$')
emptyparamsre = re.compile(r'\|\s*(archi(ef|ve)-?url|archiefdatum|archive-?date|dode-?url|dead-?url)\s*=\s*(?=[|}])')
archiefre = re.compile(r'archi(ef|ve)-?url\s*=\s*http')
dodeurlre = re.compile(r'(dode|dead)-?url\s*=\s*(ja|unfit|usurped|bot: unknown)|url-?status\s*=\s*dead')
refre = re.compile('<ref[^/]*?>.*?</ref>', flags=re.DOTALL)
dodelinkre = re.compile(r'\{\{\s*[Dd](ode link|ood|ead link)\s*[|}]')
tweetre = re.compile(r'https://twitter\.com/(.*)/status/(\d+)')
citeertweetre = re.compile(r'\{\{\s*[Cc]ite(er)? tweet\s*\|')

maandnrs = {"januari": '01', "februari": '02', "maart": '03', "april": '04', "mei": '05', "juni": '06', "juli": '07', "augustus": '08', "september": '09', "oktober": '10', "november": '11', "december": '12',
    "january": '01', "february": '02', "march": '03', "may": '05', "june": '06', "july": '07', "august": '08', "october": '10',
    "januar": '01', "februar": '02', "märz": '03', "mai": '05', "dezember": '12',
    "janvier": '01', "février": '02', "mars": '03', "avril": '04', "juin": '06', "julliet": '07', "août": '08', "septembre": '09', "octobre": '10', "novembre": '11', "décembre": '12'}
maanden = list(maandnrs)[0:12]

# Voor general fixes aan het eind:
contractre = re.compile(r'\|( *)contract tot( *)=')
bestandre = re.compile(r'\[\[\s*(Afbeelding|File|image):', flags = re.IGNORECASE)
categoriere = re.compile(r'\[\[\s*[Cc]ategorie\s*:\s*(\S)')
defaultsortre = re.compile(r'\{\{DEFAULTSORT:(\w+),(\w+)\}\}')
appendixre = re.compile(r'\{\{Appendix *\|( *1 *= *alles *\|)? *2 *=\s*\{\{[Rr]eferen(ces|ties)\}\}\s*\}\}')
exlinkre = re.compile(r'== *Externe [Ll]inks *== *(?=\n\n?\*.*\n+[^*])')
exlinksre = re.compile(r'== *Externe [Ll]ink *== *(?=\n\n?\*.*\n+\*)')
kerkre = re.compile(r'-katholieke Kerk( *)\|')
spatierefre = re.compile(r"([^-|'=]) <ref")
puntrefpuntre = re.compile(r"([.,!?;])(<ref[^<>]*?>[^<>]*?</ref>)\1")
clearleftrightre = re.compile(r'\{\{\s*[Cc]lear\s*\|\s*(left|right)\s*\}\}')
clearre = re.compile(r'\{\{\s*[Cc]lear\s*\}\}')
cursiefre = re.compile(r'</?[Ii]>')
isxnre = re.compile(r'\bIS(B|S)N ((\d|\-|X|x| (?=\d))+)')

def tempcall(text, start):
    pos = start + 2
    nest = 1
    while nest > 0:
        nextstart = text.find('{{', pos)
        nextend = text.find('}}', pos)
        if nextend == -1:
            return ''
        if nextstart > -1 and nextstart < nextend:
            nest += 1
            pos = nextstart + 2
        else:
            nest -= 1
            pos = nextend + 2
    return text[start:pos]

tempre = re.compile(r'\{\{\[^{}]*\}\}')

def stripsubtemplates(text):
    subtemps = tempre.findall(text, 2)
    while subtemps != []:
        for s in subtemps:
            text = text.replace(s, '')
        subtemps = tempre.findall(text, 2)
    return text

def istweet(citeercall, url):
    citeertweetmatch = citeertweetre.search(citeercall)
    urlmatch = tweetre.fullmatch(url)
    if citeertweetmatch and urlmatch:
        if re.search(r'(author|auteur|user|gebruiker)\s*=\s*' + re.escape(urlmatch.group(1)), citeercall):
            if re.search(r'num[bm]er\s*=\s*' + re.escape(urlmatch.group(2)), citeercall):
                return True
    return False

def getArchiveOrg(url, bezochtdatum = ''):
    timestamp = ''
    archiefurl = ''
    archiefdatum = ''
    archivesaved = False
    if datumre1.search(bezochtdatum):
        bdsplit = bezochtdatum.split('-')
        timestamp = bdsplit[0] + bdsplit[1] + bdsplit[2]
    elif datumre2.search(bezochtdatum):
        bdsplit = bezochtdatum.split('-')
        timestamp = bdsplit[2] + bdsplit[1] + bdsplit[0]
    elif datumre3.search(bezochtdatum):
        bdsplit = bezochtdatum.split(' ')
        maand = bdsplit[1].lower()
        if maand in maandnrs:
            timestamp = bdsplit[2] + maandnrs[maand] + bdsplit[0]
    try:
        archiveget = requests.get('https://archive.org/wayback/available?url=' + url + '&timestamp=' + timestamp, timeout = 60)
    except:
        return archiefurl, archiefdatum, archivesaved
    archivematch = archiveorgre.search(archiveget.text)
    if archivematch: # Er is dan een archiefpagina beschikbaar.
        archiefurl = 'https://' + archivematch.group(0)[7:]
        if url in archiefurl:
            archiefdatum = archiefurl[28:32] + '-' + archiefurl[32:34]+ '-' + archiefurl[34:36]
        else: # Dit gebeurt bijv. als sommige parameters niet meekomen in archiefurl.
            archiefurl = ''
    else: # Geen archiefpagina beschikbaar, dus save aanvragen:
        print('Save aanvragen op Archive.org ...')
        try:
            archiveget = requests.get('https://web.archive.org/save/' + url, timeout = 120)
        except:
            print('Time-out')
            return archiefurl, archiefdatum, archivesaved
        print('Archiefurl = ' + archiveget.url)
        # Voor het voorkomen van problemen met bijv. cookiewalls:
        if archiveget.url.startswith('https://web.archive.org/web') and url in archiveget.url:
            archiefurl = archiveget.url
            vandaag = datetime.date.today()
            archiefdatum = str(vandaag.year) + '-' + str(vandaag.month).rjust(2, '0') + '-' + str(vandaag.day).rjust(2, '0')
            archivesaved = True
    return archiefurl, archiefdatum, archivesaved

def categoriereplace(m):
    return '[[Categorie:' + m.group(1).upper()

##titelre = re.compile('^[A-Z]') # Voor als alle beginletters gedaan zijn.
prefix = input('Voer de eerste letters van de paginatitels in: ')
p = 0
for page in site.allpages(namespace = 0, prefix = prefix, filterredir = False):
    p += 1
    # if titelre.search(page.title()):
    #     continue
    if 'edit' in page.protection().keys() and page.protection()['edit'][0] == 'sysop':
        continue
    print('\n', p, page.title())
    starttijd = site.server_time()
    pagechanged = False
    nsaves = 0
    for url in list(page.extlinks()):
        if url not in page.text and 'twitter.com' not in url:
            continue # {{Citeer tweet}} geeft geen url in de brontekst, maar de pagina linkt er wel heen.
        if 'marinespecies.org' in url or 'carabidae.org/search' in url:
            continue # Marinespecies.org geeft vaak http://web.archive.org/web/20201111192837/http://marinespecies.org/aphia.php?p=taxdetails, die niet werkt.
        if 'saaremaa.ee' in url or 'stat.ee/' in url:
            continue # N.a.v. opmerking op mijn overlegpagina.
        if url.startswith('http://web.archive.org'):
            page.text = page.text.replace(url, 'https://' + url[7:])
            pagechanged = True
            continue
        if 'archive.' in url:
            continue
        print('* ' + url)
        try:
            urlhead = requests.head(url, timeout = 60)
            if urlhead.status_code == 301 and urlhead.next.url == 'https://' + url[7:]:
                page.text = page.text.replace(url, urlhead.next.url)
                pagechanged = True
                url = urlhead.next.url
                urlhead = requests.head(url, timeout = 60)
            if urlhead.status_code > 399 and urlhead.status_code != 403: # Twitter geeft 403.
                continue
        except:
            continue

        archiefurl = ''
        archiefdatum = ''
        archivesaved = False
        dodelink = False

        # Voor citeersjablonen, al dan niet binnen een <ref>:
        m = citeerstartre.search(page.text)
        while m:
            citeercall = tempcall(page.text, m.start())
            pos = m.start() + len(citeercall)
            callstripped = stripsubtemplates(citeercall)
            if dodeurlre.search(callstripped) or dodelinkre.search(page.text, pos, pos + 20):
                # De URL is gemarkeerd als dood; soms verwijst zo'n URL door naar de homepage,
                # met http-statuscode 200, of is de URL overgenomen door iemand anders (geüsurpt).
                dodelink = True
                break
            if (url in callstripped or istweet(callstripped, url)) and not archiefre.search(callstripped):
                # De URL staat dan in de sjabloonaanroep en de parameter archiefurl is nog leeg.
                bezochtdatummatch = bezochtdatumre.search(callstripped)
                if bezochtdatummatch:
                    bezochtdatum = bezochtdatummatch.group(2)
                else:
                    bezochtdatum = ''
                archiefurl, archiefdatum, archivesaved = getArchiveOrg(url, bezochtdatum)
                if archiefurl:
                    archiefparams = ' |archiefurl=' + archiefurl + ' |archiefdatum=' + archiefdatum
                    newciteerstring = re.sub(emptyparamsre, '', citeercall)
                    newciteerstring = newciteerstring[:-2] + archiefparams + '}}'
                    page.text = page.text.replace(citeercall, newciteerstring)
                    pagechanged = True
                    pos += len(archiefparams) # Daarom kan het niet met re.finditer.
            m = citeerstartre.search(page.text, pos)
        if dodelink:
            continue

        # Voor <ref>'s zonder citeersjabloon:
        refmatches = refre.findall(page.text)
        for m in refmatches:
            if 'archive.' in m or (url not in m) or citeerstartre.search(m):
                continue
            if dodelinkre.search(m):
                dodelink = True
                break
            if not archivesaved:
                geraadpleegdmatch = geraadpleegdre.search(m)
                if geraadpleegdmatch:
                    bezochtdatum = geraadpleegdmatch.group(3)
                else:
                    bezochtdatum = ''
                archiefurl, archiefdatum, archivesaved = getArchiveOrg(url, bezochtdatum)
            if archiefurl:
                datumOK = True
                try:
                    archiefdatum = archiefdatum[8:10].lstrip('0') + ' ' + maanden[int(archiefdatum[5:7])-1] + ' ' + archiefdatum[0:4]
                except:
                    datumOK = False
                if datumOK:
                    if m.removesuffix('</ref>').strip(' ]\n')[-1] == '.':
                        newrefstring = m[:-6] + ' [' + archiefurl + ' Gearchiveerd] op ' + archiefdatum + '.</ref>'
                    else:
                        newrefstring = m[:-6].rstrip() + '. [' + archiefurl + ' Gearchiveerd] op ' + archiefdatum + '.</ref>'
                    page.text = page.text.replace(m, newrefstring)
                    pagechanged = True
        if archivesaved:
            nsaves += 1
        if dodelink or archiefurl:
            continue
        
        # Als de url alleen voorkomt zonder <ref> of citeersjabloon:
        archiefurl, archiefdatum, archivesaved = getArchiveOrg(url)
        if archivesaved:
            nsaves += 1
    # Alle URL's gehad.
    
    if not pagechanged:
        continue
    page.text = re.sub(contractre, r'|\1contracttot\2=', page.text)
    page.text = re.sub(bestandre, r'[[Bestand:', page.text)
    page.text = re.sub(categoriere, categoriereplace, page.text)
    page.text = re.sub(defaultsortre, r'{{DEFAULTSORT:\1, \2}}', page.text)
    page.text = re.sub(appendixre, r'{{Appendix}}', page.text)
    page.text = re.sub(exlinkre, r'== Externe link ==', page.text)
    page.text = re.sub(exlinksre, r'== Externe links ==', page.text)
    page.text = re.sub(kerkre, r'-Katholieke Kerk\1|', page.text)
    page.text = re.sub(spatierefre, r'\1<ref', page.text)
    page.text = re.sub(puntrefpuntre, r'\1\2', page.text)
    page.text = re.sub(clearleftrightre, r'{{Clear\1}}', page.text)
    page.text = re.sub(clearre, r'{{Clearboth}}', page.text)
    page.text = re.sub(cursiefre, "''", page.text)
    page.text = re.sub(isxnre, r'{{IS\1N|\2}}', page.text)
    page.text = page.text.replace('{{Authority control', '{{Bibliografische informatie')
    
    summary = '[[Speciaal:Permalink/60259738|Botverzoeken]]: '
    if nsaves == 1:
        summary += '1 link gearchiveerd, '
    elif nsaves > 1:
        summary += str(nsaves) + ' links gearchiveerd, '
    summary += 'toevoegen archieflinks en vervangen http:// door https://'
    if page.editTime() > starttijd:
        print('Bewerkingsconflict: de bewerking is niet gepubliceerd.')
    else:
        try:
            page.save(summary)
        except Exception as e:
            print('De pagina kon niet opgeslagen worden:')
            print(e.args)