Χρήστης:AtouBot/generate-iw-actionlist.sh
Όνομα εργαλείου: generate-iw-actionlist.sh
Περιγραφή:
Το generate-iw-actionlist.sh το τρέχουμε πάνω σε αρχείο XML του Βικιλεξικού για να δημιουργήσουμε έναν κατάλογο προτεινόμενων αλλαγών (προσθέσεων ή αφαιρέσεων) στους συνδέσμους προς το ίδιο λήμμα σε άλλες γλώσσες (interwikilinks). Αυτοί οι σύνδεσμοι έχουν τη μορφή [[fr:λήμμα]] (για παράδειγμα) στο wikitext και εμφανίζονται ως όνομα γλώσσας στη στήλη αριστερά στην σελίδα που βλέπει ο αναγνώστης.
Βάζουμε τέτοιους συνδέσμους προς το ίδιο λήμμα σε αλλόγλωσσα Βικιλεξικά ανεξάρτητα αν οι σελίδες αυτές είναι ανακατευθύνσεις προς άλλα λήμματα ή όχι.
Η διαδικασία συνοπτικά έχει ως εξής:
- Διαβάζουμε το αρχείο XML των δικών μας λημμάτων.
- Βγάζουμε ό,τι δεν είναι λήμμα (πχ. σελίδες συζήτησης κλπ).
- Μαζεύουμε τα interwikis που υπάρχουν ήδη για κάθε λήμμα και τα καταγράφουμε.
- Για κάθε Βικιλεξικό, κατεβάζουμε από το dumps.wikimedia.org το αρχείο με όλους τους τίτλους των λημμάτων.
- Ζητάμε τους τίτλους όλων των νέων σελίδων, όλων των διαγραφών, όλων των εισαγωγών και όλων των μετακινήσεων που έχουν γίνει από τότε που φτιάχτηκε το αρχείο τίτλων.
- Δημιουργούμε ενημερωμένο αρχείο τίτλων.
- Μαζεύουμε όλους τους τίτλους ανά εγχείρημα, και καταγράφουμε τα λήμματα μαζί με τις γλώσσες των Βικιλεξικών στα οποία υπάρχουν τα λήμματα.
- Πετάμε από αυτή τη λίστα τα λήμματα που δεν υπάρχουν στο δικό μας Βικιλεξικό, δεν μας αφορούν.
- Τώρα έχουμε: τα iwikis που υπάρχουν στις σελίδες του δικού μας Βικιλεξικού, και τα iwikis όπως θα έπρεπε να είναι. Συγκρίνουμε, και δημιουργούμε μια λίστα με αφαιρέσεις/προσθέσεις ανά λήμμα.
Εντολή
Το κυρίως πρόγραμμα, αυτό που τρέχει ο τελικός χρήστης, είναι το generate-iw-actionlist.sh.
Παράμετροι:
- --skipdownload
- Δεν ξανακατεβάζουμε τα αρχεία τίτλων λημμάτων, ακόμα κι αν υπάρχουν καινούργια που δεν τα έχουμε εμείς.
- --skipupdate
- Δεν ζητάμε τις νέες σελίδες, τις διαγραφές κλπ για τα διάφορα ΒΛ, ακόμα κι αν υπάρχουν.
- όνομα-αρχείου-XML
- Το πρόγραμμα διαβάζει σελίδες XML από αυτό το αρχείο. Θα πρέπει να είναι σε μορφή bz2 (bzip2).
- όνομα-προτεινόμενων-αλλαγών-iwikis
- Το πρόγραμμα γράφει τη λίστα αλλαγών σε αυτό το αρχείο, που αποθηκεύεται και στον τρέχοντα κατάλογο και στον κατάλογο iws_tmp.
Παραδείγματα:
- generate-iw-actionlist.sh ~/getrcs/last_full.xml.bz2 iw-action-list.txt
- generate-iw-actionlist.sh --skipdownload ~/getrcs/last_full.xml.bz2 iw-action-list.txt
- generate-iw-actionlist.sh --skipdownload --skipupdate ~/getrcs/last_full.xml.bz2 iw-action-list.txt
Προϋποθέσεις:
- περιβάλλον unix/linux ή περιβάλλον με τις εντολές sed, sort, bzcat, cat, grep
- οι εντολές curl και wget
- perl, python (ναι, και τις δύο γλώσσες, ήμουν αναποφάσιστος :-P)
- ενημερωμένο αρχείο XML από το Βικιλεξικό (δείτε το getrcs.sh για περισσότερες πληροφορίες)
Προγράμματα:
Άλλα προγράμματα που καλούνται από το generate-iw-actionlist.sh είναι τα εξής:
- xml-σελίδες-ns0.pl (δείτε τη σελίδα του)
- dump-our-iws.py
- περιγραφή: διαβάζει αρχείο XML με το περιεχόμενο των λημμάτων ενός Βικιλεξικού από το stdin και γράφει στο stdout μια λίστα των iwikis ανά λήμμα
- παράμετροι: --dir (ο κατάλογος που περιέχει τα αρχεία all.dblist και closed.dblist)
- παράδειγμα: cat full-ns0.xml | python dump-our-iws.py --dir=iws_tmp > our-iws.txt
- getlemmasfromproject.pl
- περιγραφή: κατεβάζει αρχείο με τους τίτλους λημμάτων ενός ορισμένου Βικιλεξικού, παίρνει τους τίτλους σελίδων που δημιουργήθηκαν, σβήστηκαν κλπ από τότε που φτιάχτηκε το αρχείο, ενημερώνει τη λίστα τίτλων, και τη γράφει στο αρχείο με όνομα xxwiktionary-latest-all-titles-in-ns0.final, στο οποίο το xx είναι κωδικός γλώσσας, πχ. fr, ru.
- παράμετροι: --skipdownload δεν κατεβάζουμε αρχείο, --skipupdate δεν ενημερώνουμε τη λίστα λημμάτων, --lang ο κωδικός γλώσσας
- παράδειγμα: perl ../getlemmasfromproject.pl --skipdownload --lang=ar
- sortlemmas.sh
- περιγραφή: ταξινόμηση περιεχομένου με βάση το locale C
- παράμετροι: αρχείο που θα διαβαστεί, αρχείο που θα γραφτεί
- παράδειγμα: sortlemmas.sh to-be-sorted outputfile
- langs-per-lemma.pl
- περιγραφή: διαβάζει από το stdin μια (ταξινομημένη) λίστα λημμάτων με τον κωδικό γλώσσας του Βικιλεξικού στο οποίο υπάρχει, και γράφει στο stdout κάθε λήμμα μαζί με όλες τις γλώσσες των ΒΛ του στην ίδια γραμμή
- παράμετροι: δεν υπάρχουν
- toss-extra-titles.py
- περιγραφή: διαβάζει από το stdin μία λίστα λημμάτων με τις γλώσσες του καθενός στην ίδια γραμμή, διαβάζει από ένα αρχείο τα λήμματα που θέλουμε να κρατήσουμε, και γράφει μόνο αυτές τις γραμμές στο stdout
- παράμετροι: --file αρχείο με λήμματα
- παράδειγμα: cat langs-per-lemma.txt | python toss-extra-titles.py --file=our-iws.txt > their-iws.txt
- check-our-iws.py
- περιγραφή: διαβάζει δύο αρχεία, το ένα περιέχει τα iwikis που έχουμε εμείς και το άλλο περιέχει (υποθετικά) τα iwikis που θα έπρεπε να υπάρχει (δηλαδή ποια Βικιλεξικά έχουν πράγματι το ορισμένο λήμμα) και γράφει στο stdout μια λίστα προτεινόμενων αλλαγών iwikis
- παράμετροι: --ouriwfile λίστα των δικών μας iwikis, --theiriwfile λίστα "πραγματικών" iwikis
- παράδειγμα: check-our-iws.py --ouriwfile=our-iws.txt --theiriwfile=their-iws.txt > proposed-changes.txt
Αρχεία/κατάλογοι:
- iws_tmp/
- όλα τα αρχεία δημιουργούνται εδώ
- all.dblist
- λίστα όλων των ενεργών Βικιλεξικών
- closed.dblist
- λίστα όλων των κλειδωμένων Βικιλεξικών
- xxwiktionary-latest-all-titles-in-ns0.gz
- το xx αντιστοιχεί με κωδικό ISO για μια γλώσσα (πχ. en, fr)
- αρχείο με τίτλους όλων των λημμάτων ενός Βικιλεξικού, όπως κατεβάστηκε
- xxwiktionary-latest-all-titles-in-ns0
- αρχείο με τίτλους όλων των λημμάτων ενός Βικιλεξικού, με χρόνοσφραγίδα
- xxwiktionary-latest-all-titles-in-ns0.updated
- αρχείο με τίτλους όλων των λημμάτων ενός Βικιλεξικού, ενημερωμένο με νέες σελίδες, διαγραφές κλπ.
- xxwiktionary-latest-all-titles-in-ns0.final
- αρχείο με τίτλους όλων των λημμάτων ενός Βικιλεξικού, με κωδικό γλώσσας
- all-lemmas.txt
- αρχείο με τίτλους όλων των λημμάτων όλων των Βικιλεξικών, με κωδικό γλώσσας
- all-lemmas-sorted.txt
- αρχείο με τίτλους όλων των λημμάτων όλων των Βικιλεξικών, με κωδικό γλώσσας, ταξινομημένο ανά λήμμα
- langs-per-lemma.txt
- αρχείο με τίτλους όλων των λημμάτων που υπάρχουν σε έστω κι ένα Βικιλεξικό, μαζί με τις γλώσσες των Βικιλεξικών στα οποία υπάρχουν
- their-iws.txt
- αρχείο με τίτλους όλων των λημμάτων που υπάρχουν στο δικό Βικιλεξικό, μαζί με τις γλώσσες των άλλων Βικιλεξικών στα οποία υπάρχουν
→ Πίσω στα Εργαλεία |
generate-iw-actionlist.sh
επεξεργασία#!/bin/bash
# This script generates an iw action list from scratch.
# the contents of said file look like
#
# șarpe||addition:ru fr en ro io
# abut||removal:cs
# téléphone||removal:mg||addition:eu
#
# and so on.
# It takes 2 mandatory arguments:
#
# 1) the name of the full xml file from el wikt,
# presumably updated with getrcs.sh
#
# 2) the name of the output file for the action list.
#
# and two optional arguments:
#
# 1) --skipdownload
#
# 2) --skipupdate
#
# It produces a number of intermediate files,
# described below. These are not removed, in case
# the user wants to reuse any of them at any time.
# In particular the downloaded lists of titles
# from each wiktionary is kept intact so that
# future updates won't re-download the same files
# if no newer one is available.
# All intermediate files are written to the subdir
# iws_tmp
#
usage() {
echo "Usage: $0 [--skipdownload] [--skipupdate] fullxmlfile outputfile"
echo
echo " fullxmlfile name of the xml file with current page contents"
echo " outputfile name of file to which we will write iw action list"
echo " --skipdownload don't download new titles-ns0 files, work with existing ones"
echo " --skipupdate don't update titles-ns0 files, work with existing data"
echo
echo "For example:"
echo " $0 ~/getrcs/last_full.xml.bz2 iw-action-list.txt"
echo " $0 --skipdownload ~/getrcs/last_full.xml.bz2 iw-action-list.txt"
echo " $0 --skipdownload --skipupdate ~/getrcs/last_full.xml.bz2 iw-action-list.txt"
exit 1
}
if [ "$#" -lt "2" -o "$#" -gt "4" ]; then
usage
fi
skipdownload=""
skipupdate=""
infile=""
outfile=""
for i in $@; do
if [ $i == "--skipdownload" ]; then
skipdownload="--skipdownload"
elif [ $i == "--skipupdate" ]; then
skipupdate="--skipupdate"
elif [ -z "$infile" ]; then
infile="$i"
else
outfile="$i"
fi
done
if [ ! -e "$infile" ]; then
echo "Error: Failed to find file $infile"
echo
usage
fi
if [ ! -e "iws_tmp" ]; then
mkdir iws_tmp
fi
filetype=`file $infile | grep bzip2`
if [ -z "$filetype" ]; then
echo "Input file should be bzip2-compressed file."
echo
usage
fi
echo "removing all pages not in ns0 from dump file"
bzcat $infile | perl xml-σελίδες-ns0.pl > iws_tmp/full-ns0.xml
echo "generating list of iws per lemma from our xml dump file"
#cat iws_tmp/full-ns0.xml | python dump-our-iws.py | grep -v 'unicode test: triggers problem' > iws_tmp/our-iws.txt
cat iws_tmp/full-ns0.xml | python dump-our-iws.py --dir=iws_tmp > iws_tmp/our-iws.txt
echo "getting list of all wiktionaries"
cd iws_tmp/
wget -N -q 'http://noc.wikimedia.org/conf/all.dblist'
wget -N -q 'http://noc.wikimedia.org/conf/closed.dblist'
cd ..
if [ ! -e "iws_tmp/all.dblist" ]; then
echo "Failed to retrieve http://noc.wikimedia.org/conf/all.dblist, exiting"
exit 1
fi
if [ ! -e "iws_tmp/closed.dblist" ]; then
echo "Failed to retrieve http://noc.wikimedia.org/conf/closed.dblist, exiting"
exit 1
fi
langs=`cat iws_tmp/all.dblist | grep wiktionary | sed -e 's/wiktionary//g;'`
echo "generating current list of lemmas for each project"
cd iws_tmp/
for i in $langs; do
perl ../getlemmasfromproject.pl $skipdownload $skipupdate --lang=$i
done
cd ..
echo "generating list of all lemmas on all projects"
cat iws_tmp/*final > iws_tmp/all-lemmas.txt
echo "sorting list of lemmas"
bash sortlemmas.sh iws_tmp/all-lemmas.txt iws_tmp/all-lemmas-sorted.txt
echo "collecting languages per lemma"
cat iws_tmp/all-lemmas-sorted.txt | perl langs-per-lemma.pl | grep -vaP "\xc2\x85" > iws_tmp/langs-per-lemma.txt
echo "getting rid of all entries not contained in our wiktionary"
cat iws_tmp/langs-per-lemma.txt | python toss-extra-titles.py --file=iws_tmp/our-iws.txt > iws_tmp/their-iws.txt
echo "writing iw action list"
python check-our-iws.py --ouriwfile=iws_tmp/our-iws.txt --theiriwfile=iws_tmp/their-iws.txt > iws_tmp/$outfile
echo "making copy of $outfile in current directory"
cp iws_tmp/$outfile .
echo "done! please check $outfile for your results."
exit 0
xml-σελίδες-ns0.pl
επεξεργασίαΟ κώδικας βρίσκεται εδώ.
dump-our-iws.py
επεξεργασία#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys, getopt
import re, codecs
sys.stdin = codecs.getreader("utf-8")(sys.stdin)
sys.stdout = codecs.getwriter("utf-8")(sys.stdout)
class languageLinks(object):
def __init__(self, fileLocation = ""):
if fileLocation:
if not fileLocation.endswith('/'):
fileLocation = fileLocation + '/'
self.validLangs = self.getLanguages('wiktionary',fileLocation + 'all.dblist')
self.obsoleteLangs = self.getLanguages('wiktionary',fileLocation + 'closed.dblist')
def getLanguages(self, family, filename):
langs = []
try:
langfile = open(filename,'r')
except:
print "failed to open file ", filename
raise
line = langfile.readline()
while line != "":
line = line.strip()
if line.endswith(family):
line = line.replace(family,'')
# cases like zh_min_nan
line = line.replace('_','-')
langs.append(line)
line = langfile.readline()
langfile.close()
return langs
class iwLinkRetriever(object):
def __init__(self, fileDir = ""):
self.langLinks = languageLinks(fileDir)
self.regexes = {
'comment': r'(?s)<!--.*?-->',
'nowiki': r'<nowiki>.*?</nowiki>',
'pre': r'<pre>.*?</pre>',
}
tags = self.regexes.keys()
self.toRemove = re.compile('|'.join([self.regexes[tag] for tag in tags]),
re.IGNORECASE | re.DOTALL)
self.interwikiregexp = re.compile(u'(?i)\[\[\s*(?:%s)\s*:\s*[^\]]+\]\]'
% '|'.join(self.langLinks.validLangs + self.langLinks.obsoleteLangs))
# from pywikipediabot
def unescape(self, s):
"""Replace escaped HTML-special characters by their originals"""
if '&' not in s:
return s
s = s.replace('<', "<")
s = s.replace('>', ">")
s = s.replace(''', "'")
s = s.replace('"', '"')
s = s.replace('&', "&") # Must be last
return s
# from pywikipediabot
def removeComments(self, text):
# remove comments, also skip stuff in <nowiki> tags
return self.toRemove.sub('', text)
def getIWLinks(self, keimeno):
iws = {}
text = self.unescape(keimeno)
text = self.removeComments(text)
iws = self.interwikiregexp.findall(text)
iwhash = {}
for iw in iws:
key,value = iw.split(':',1)
key = key.strip()
key = key.lstrip('[')
value = value.strip()
value = value.rstrip(']')
iwhash[key] = value
return iwhash
def getiws(self, title, keimeno, site):
interwiki = self.getIWLinks(keimeno)
for key in interwiki.keys():
# keep only if the iw points to the same word
if interwiki[key] == title:
sys.stdout.write('||')
sys.stdout.write(key)
sys.stdout.write('||')
# include ourselves
sys.stdout.write(site)
print
class Xmlparse(object):
def __init__(self, filename = None, fileDir = ""):
self.filename = filename
self.xmltags()
self.getIWs = iwLinkRetriever(fileDir)
def xmltags(self):
self.titleStart = re.compile('<title>')
self.titleContent = re.compile('<title>(.*)<\/title>')
self.textStart = re.compile('<text ')
self.textEnd = re.compile('<\/text>')
self.redir = re.compile('<redirect ')
def openfile(self):
if (self.filename):
self.fin = open(self.filename,"r", "utf-8")
else:
self.fin = sys.stdin
def parsefile(self):
self.openfile()
pageTitle=""
arxiko=""
inText = False
redir = False
line = self.fin.readline()
while not line == "":
if inText:
arxiko = arxiko + line
if self.textEnd.search(line):
inText = False
sys.stdout.write(pageTitle)
self.getIWs.getiws(pageTitle, arxiko, 'el')
arxiko=""
elif self.titleStart.search(line):
result = self.titleContent.search(line)
pageTitle=result.group(1)
redir = False
elif self.redir.search(line):
redir = True
elif self.textStart.search(line) and not redir:
arxiko = arxiko + line
if (not self.textEnd.search(line)):
inText = True
else:
sys.stdout.write(pageTitle)
self.getIWs.getiws(pageTitle, arxiko, 'el')
arxiko=""
line = self.fin.readline()
def usage(message = None):
if message:
print >> sys.stderr, message
print >> sys.stderr, "Usage: dump-our-iws.py --dir=location"
print >> sys.stderr, " where location is the directory where all.dblist and"
print >> sys.stderr, " closed.dblist are located"
sys.exit(1)
def getOpts():
dir = ""
try:
(options, remainder) = getopt.gnu_getopt(sys.argv[1:], "", ['dir='])
except:
usage("Unknown option specified")
for (opt, val) in options:
if opt == "--dir":
dir = val
return dir
if __name__ == "__main__":
fileDir = getOpts()
xmlParser = Xmlparse(fileDir=fileDir)
xmlParser.parsefile()
getlemmasfromproject.pl
επεξεργασία#!/usr/bin/perl
# Encoding : UTF8
# Is used with RAW XML !!!
#
sub get_opts {
my $download = 1;
my $update = 1;
if ($#ARGV > 2 || $#ARGV < 0) {
print STDERR "Usage: $0 --skipdownload --skipupdate --lang=lang-code\n";
exit 1;
}
foreach $arg (@ARGV) {
if ($arg eq "--skipdownload") {
$download =0;
}
elsif ($arg =~ /^--lang=/) {
($opt, $lang) = split(/=/,$arg);
}
elsif ($arg eq "--skipupdate") {
$update = 0;
}
else {
print STDERR "Usage: $0 --skipdownload --skipupdate --lang=lang-code\n";
exit 1;
}
}
return($download, $update, $lang);
}
sub get_url {
my $lang = shift(@_);
my $url1 = "http://download.wikimedia.org/" ;
my $url2 = "wiktionary/latest/" ;
my $url3 = "wiktionary-latest-all-titles-in-ns0" ;
my $url = "$url1$lang$url2$lang$url3.gz";
return($url);
}
sub download_file {
my $filename = shift(@_);
my $url = shift(@_);
my $retrycount = 5;
my $result = `wget -N -q $url` ;
while ($retrycount && ( ! -e "$filename.gz" ) ) {
print STDERR "WARNING: failed to download $url\n";
print STDERR "WARNING: retrying\n";
sleep 6;
$retrycount--;
$result = `wget -N -q $url` ;
}
return ($result);
}
sub get_mtime_of_file_minus_fudge {
my $filename = shift(@_);
# first, mark all entries with timestamp
my @statinfo = stat( $filename );
if (@statinfo == () ) {
return (0, "");
}
# get last modified
my $time_in_secs = @statinfo[9];
# adjust for length of time it might have taken to run the file, say 4 hour (this
# is a vast overestimation)
my $time_in_secs = $time_in_secs - (3600*4);
my $ts = get_timestamp($time_in_secs);
return($time_in_secs, $ts);
}
# takes time in secs as returned by time() for example
sub get_timestamp {
my $time = shift(@_);
# convert to this form: <timestamp>2009-11-10T16:32:30Z</timestamp>
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time);
# year is counted since 1900 for gmtime
$year += 1900;
# month starts from 0 for gmtime
$mon++;
my $timestamp = sprintf("%4d-%02d-%02dT%02d:%02d:%02dZ", $year, $mon, $mday, $hour, $min, $sec);
return($timestamp);
}
sub process_titles_ns0_file {
my $timestamp = shift(@_);
my $filename = shift(@_);
local (*FIN);
local (*OUT);
open(FOUT, ">", "$filename");
print (FOUT "$timestamp\n");
open(FIN, "zcat -n '$filename.gz'|");
# first line is crap
my $line = <FIN>;
while (<FIN>) {
chomp($_);
print(FOUT $_."|".$timestamp."\n");
}
close(FIN);
close(FOUT);
}
sub create_titles_ts_hash {
my $filename = shift(@_);
my %wikititles = ();
local (*FIN);
open(FIN,"<",$filename);
# first line is the timestamp (changes later than this will not be reflected
# in the file)
my $line = <FIN>;
chomp($line);
my $timestamp = $line;
while (<FIN>) {
chomp($_);
my ($title, $ts) = split(/\|/,$_);
$wikititles{$title} = $ts;
}
close(FIN);
return($timestamp, %wikititles);
}
sub write_updated_file {
my $filename = shift(@_);
my $fileout = shift(@_);
my $timestamp = shift(@_);
my $wikititlesref = shift(@_);
my %wikititles = %$wikititlesref;
local (*FIN);
local (*FOUT);
open(FOUT, '>', $fileout);
print(FOUT "$timestamp\n");
foreach $key (keys(%wikititles)) {
$key1 = $key;
$key1 =~ s/'/'/g;
print(FOUT "$key1|$wikititles{$key}\n");
}
close(FOUT);
return;
}
sub write_titles_with_langs {
my $filename = shift(@_);
my $fileout = shift(@_);
my $lang = shift(@_);
local (*FIN);
open( FIN, "<", $filename ) ;
open( FOUT, ">", $fileout ) ;
my $line = <FIN> ;
# skip first line, it's timestamp
while ( <FIN> ) {
$_ =~ s/_/ /g;
chomp($_);
my ($title, $rest) = split(/\|/,$_);
print (FOUT $title."||".$lang."\n");
}
}
sub get_new_titles {
my $rcstartdate = shift(@_);
my $rcenddate = shift(@_);
my $wikititlesref = shift(@_);
my %wikititles = %$wikititlesref;
my $lang = shift(@_);
my $oldinput = "";
while (1) {
print (STDERR "getting new titles $rcstartdate to $rcenddate\n");
$input=`curl -s --retry 10 -H Expect: -f "http://$lang.wiktionary.org/w/api.php?action=query&list=recentchanges&rclimit=500&rctype=new|edit&format=xml&rcstart=$rcstartdate&rcend=$rcenddate&rcnamespace=0&rctype=new"`;
if ($input eq "") {
die ("Error from curl, unable to get recent changes, bailing\n");
}
if ($oldinput eq $input) {
last;
}
if ($input =~ /<recentchanges \/>/) {
last;
}
$oldinput = $input;
@chunks = split(/>/,$input);
foreach $chunk (@chunks) {
if ($chunk =~ /<rc type=/) {
if ($chunk =~ m/title="([^"]+)".*timestamp="([^"]+)"/) {
$this_title = $1;
$this_timestamp = $2;
unless ($wikititles{$this_title}) {
$wikititles{$this_title} = $this_timestamp;
} else {
$wikititles{$this_title} = $this_timestamp if ($wikititles{$this_title} lt $this_timestamp) ;
}
}
}
}
# παίρνουμε το χρονοσφραγίδα από την τελευταία γραμμή
$nextstartdate = $this_timestamp;
$rcstartdate=$nextstartdate;
}
return(%wikititles);
}
sub get_moves {
my $mvstartdate = shift(@_);
my $mvenddate = shift(@_);
my $wikititlesref = shift(@_);
my %wikititles = %$wikititlesref;
my $lang = shift(@_);
$oldinput = "";
while (1) {
print (STDERR "getting moves $mvenddate to $mvstartdate\n");
$input=`curl -s --retry 10 -H "Expect:" -f "http://$lang.wiktionary.org/w/api.php?action=query&list=logevents&letype=move&lelimit=500&format=xml&leend=$mvstartdate&lestart=$mvenddate&ledir=newer"`;
if ($input eq "") {
die ("Error from curl, unable to get moves, bailing\n");
}
if ($oldinput eq $input) {
last;
}
$oldinput = $input;
if ($input =~ /<logevents \/>/) {
last;
}
@chunks = split(/item>/,$input);
foreach $chunk (@chunks) {
if ($chunk =~ /<item logid/) {
if ($chunk =~ /ns="([0-9]*)" title="([^"]+)".*timestamp="([^"]+)".*<move new_ns="0" new_title="([^"]+)"/) {
$old_title = $2;
$this_timestamp = $3;
$new_title = $4;
if ($wikititles{$new_title} lt $this_timestamp) {
$wikititles{$new_title} = $this_timestamp;
}
if ($wikititles{$old_title}) {
if ($wikititles{$old_title} lt $this_timestamp) {
$wikititles{$old_title} = $this_timestamp;
if ($chunk =~ / suppressedredirect=""/) {
delete($wikititles{$old_title});
}
}
}
}
}
}
$nextstartdate = $this_timestamp;
$mvenddate="$nextstartdate";
}
return(%wikititles);
}
sub get_imports {
my $impstartdate = shift(@_);
my $impenddate = shift(@_);
my $wikititlesref = shift(@_);
my %wikititles = %$wikititlesref;
my $lang = shift(@_);
$oldinput = "";
while (1) {
print (STDERR "getting imports $impstartdate to $impenddate\n");
$input=`curl -s --retry 10 -H "Expect:" -f "http://$lang.wiktionary.org/w/api.php?action=query&list=logevents&letype=import&lelimit=500&format=xml&lestart=$impstartdate&leend=$impenddate"`;
if ($input eq "") {
die ("Error from curl, unable to get imports, bailing\n");
}
if ($oldinput eq $input) {
last;
}
if ($input =~ /<logevents \/>/) {
last;
}
$oldinput = $input;
@chunks = split(/>/,$input);
foreach $chunk (@chunks) {
if ($chunk =~ /<item logid/) {
if ($chunk =~ / ns="0" /) {
if ($chunk =~ m/ title="([^"]+)".*timestamp="([^"]+)"/) {
$this_title = $1;
$this_timestamp = $2;
if ($wikititles{$this_title}) {
if ($wikititles{$this_title} lt $this_timestamp) {
$wikititles{$this_title} = $this_timestamp;
}
}
else { $wikititles{$this_title} = $this_timestamp; }
}
}
}
}
$nextstartdate = $this_timestamp;
$impstartdate="$nextstartdate";
}
return(%wikititles);
}
sub get_deletes {
my $delstartdate = shift(@_);
my $delenddate = shift(@_);
my $wikititlesref = shift(@_);
my %wikititles = %$wikititlesref;
my $lang = shift(@_);
$oldinput = "";
while (1) {
print (STDERR "getting deletes $delstartdate to $delenddate\n");
$input=`curl -s --retry 10 -H "Expect:" -f "http://$lang.wiktionary.org/w/api.php?action=query&list=logevents&letype=delete&lelimit=500&format=xml&lestart=$delstartdate&leend=$delenddate"`;
if ($input eq "") {
die ("Error from curl, unable to get imports, bailing\n");
}
if ($oldinput eq $input) {
last;
}
if ($input =~ /<logevents \/>/) {
last;
}
$oldinput = $input;
@chunks = split(/>/,$input);
foreach $chunk (@chunks) {
if ($chunk =~ /<item logid/) {
# deletions of pages, not revisions.
if ($chunk =~ / action="delete" /) {
if ($chunk =~ m/ title="([^"]+)".*timestamp="([^"]+)"/) {
$this_title = $1;
$this_timestamp = $2;
if ($wikititles{$this_title}) {
if ($wikititles{$this_title} lt $this_timestamp) {
delete($wikititles{$this_title});
}
}
}
}
# restored pages
if ($chunk =~ / action="restore" /) {
if ($chunk =~ m/ title="([^"]+)".*timestamp="([^"]+)"/) {
$this_title = $1;
$this_timestamp = $2;
unless ($wikititles{$this_title}) {
$wikititles{$this_title} = $this_timestamp;
}
else {
if ($wikititles{$this_title} lt $this_timestamp) {
$wikititles{$this_title} = $this_timestamp;
}
}
}
}
}
}
$nextstartdate = $this_timestamp;
$delstartdate="$nextstartdate";
}
return(%wikititles);
}
($download,$update,$lang) = get_opts();
print (STDERR "processing...\n");
$url = get_url($lang);
$filename = "$lang"."wiktionary-latest-all-titles-in-ns0" ;
print (STDERR "$url: ");
if ($download) {
($oldtime_in_secs, $oldtimestamp) = get_mtime_of_file_minus_fudge("$filename.gz");
$result = download_file($filename, $url);
($time_in_secs, $timestamp) = get_mtime_of_file_minus_fudge("$filename.gz");
# did we actually download it?
if ($oldtime_in_secs != $time_in_secs) {
print (STDERR "new file downloaded\n");
# and have to process it too
process_titles_ns0_file($timestamp,$filename);
unlink "$filename.updated" if (stat("$filename.updated"));
unlink "$filename.final" if (stat("$filename.final"));
}
else {
print (STDERR "no download needed\n");
}
}
else {
print (STDERR "skipping download as requested\n");
}
($time_in_secs, $timestamp) = get_mtime_of_file_minus_fudge("$filename.gz");
if (! stat($filename)) {
# we never created the title/timestamp file from the titles-ns0 file. do so now.
process_titles_ns0_file($timestamp,$filename);
# and read from it.
($timestamp, %wikititles) = create_titles_ts_hash($filename);
}
# we created the title/timestamp file but never updated it
# so read from the original
elsif (! stat("$filename.updated")) {
($timestamp, %wikititles) = create_titles_ts_hash($filename);
}
# otherwise read from the updated file
else {
($timestamp, %wikititles) = create_titles_ts_hash("$filename.updated");
}
# urls all have languange name with - in them
# and so do the iwikis, so we change it here
$lang =~ s/_/-/g;
if ($update) {
$enddate=$timestamp;
$startdatesecs=time();
$startdate=get_timestamp($startdatesecs);
# call with startdate = time of latest change we want,
# enddate = time of oldest change we want
%wikititles = get_new_titles($startdate, $enddate, \%wikititles, $lang);
%wikititles = get_moves($startdate, $enddate, \%wikititles, $lang);
%wikititles = get_imports($startdate, $enddate, \%wikititles, $lang);
%wikititles = get_deletes($startdate, $enddate, \%wikititles, $lang);
}
# allow for a bit of drift
$startdate_fudged = get_timestamp($startdatesecs -60);
if ($update) {
write_updated_file($filename, "$filename.updated", $startdate_fudged, \%wikititles);
}
write_titles_with_langs("$filename.updated", "$filename.final", $lang);
exit 0;
sortlemmas.sh
επεξεργασία#!/bin/bash
LC_ALL=C
export LC_ALL
sort $1 > $2
langs-per-lemma.pl
επεξεργασία#!/usr/bin/perl
binmode(STDOUT, ":utf8");
binmode(STDIN, ":utf8");
use encoding(UTF8);
use utf8;
$line = <STDIN>;
chomp($line);
($lemma, $value) = split(/\|\|/,$line,2);
@values = ();
push(@values, $value);
while (<STDIN>) {
chomp($_);
($curlemma, $value) = split(/\|\|/,$_,2);
if ($lemma ne $curlemma) {
print $lemma,"||", join('||',@values),"\n";
@values = ();
$lemma = $curlemma
}
push(@values, $value);
}
toss-extra-titles.py
επεξεργασία#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys, getopt
import re, codecs
#reload(sys)
#sys.setdefaultencoding('utf-8')
sys.stdin = codecs.getreader("utf-8")(sys.stdin)
sys.stdout = codecs.getwriter("utf-8")(sys.stdout)
def getOurTitles(filename):
ourTitles = set()
fin = codecs.open(filename, 'r', 'utf-8')
line = fin.readline()
while line != "":
lemma, junk = line.split('||',1)
ourTitles.add(lemma)
line = fin.readline()
# for key in ourTitles:
# print key.encode('utf-8')
fin.close()
return ourTitles
def tossExtraTitles(keepTitles):
# fin = codecs.open('langs-per-lemma.txt', 'r', 'utf-8')
line = sys.stdin.readline()
while line != "":
lemma, langs = line.split('||',1)
if lemma in keepTitles:
sys.stdout.write(line)
line = sys.stdin.readline()
# fin.close()
def usage(message = None):
if message:
print >> sys.stderr, message
print >> sys.stderr, "Usage: toss-extra-titles.py --file=filename"
sys.exit(1)
def getOpts():
try:
(options, remainder) = getopt.gnu_getopt(sys.argv[1:], "", ['file='])
except:
usage("Unknown option specified")
for (opt, val) in options:
if opt == "--file":
filename = val
if not filename:
usage()
return filename
if __name__ == "__main__":
filename = getOpts()
titles = getOurTitles(filename)
tossExtraTitles(titles)
check-our-iws.py
επεξεργασία#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys, getopt
import re, codecs
reload(sys)
sys.setdefaultencoding('utf8')
def getOurTitles(filename):
ourTitles = {}
fin = codecs.open(filename, 'r', 'utf-8')
line = fin.readline()
while line != "":
line = line.strip()
lemma, langs = line.split('||',1)
ourTitles[lemma] = set()
if ('||' in langs):
langList = langs.split('||')
else:
langList = [ langs ]
for lang in langList:
# skip us
if (lang != 'el'):
ourTitles[lemma].add(lang)
line = fin.readline()
fin.close()
return ourTitles
def getTheirTitles(filename):
theirTitles = {}
fin = codecs.open(filename, 'r', 'utf-8')
line = fin.readline()
while line != "":
line = line.strip()
lemma, langs = line.split('||',1)
theirTitles[lemma] = set()
if ('||' in langs):
langList = langs.split('||')
else:
langList = [ langs ]
for lang in langList:
# skip us
if (lang != 'el'):
theirTitles[lemma].add(lang)
line = fin.readline()
fin.close()
return theirTitles
def usage(message = None):
if message:
print >> sys.stderr, message
print >> sys.stderr, "Usage: toss-extra-titles.py --ouriwfile=filename --theiriwfile=filename"
sys.exit(1)
def getOpts():
ourfilename = ""
theirfilename = ""
try:
(options, remainder) = getopt.gnu_getopt(sys.argv[1:], "", [ 'ouriwfile=', 'theiriwfile=' ])
except:
usage("Unknown option specified")
for (opt, val) in options:
if opt == "--ouriwfile":
ourfilename = val
elif opt == "--theiriwfile":
theirfilename = val
if not ourfilename or not theirfilename:
usage()
return [ ourfilename,theirfilename ]
if __name__ == "__main__":
ourfilename, theirfilename = getOpts()
ourTitles = getOurTitles(ourfilename)
theirTitles = getTheirTitles(theirfilename)
# now we see which ones don't match and produce a list
for lemma in ourTitles:
if lemma not in theirTitles:
if len(ourTitles[lemma]):
sys.stdout.write(lemma)
sys.stdout.write('||removal:')
sys.stdout.write(" ".join(ourTitles[lemma]))
sys.stdout.write('\n')
else:
theyHave = theirTitles[lemma] - ourTitles[lemma]
addition = " ".join(theyHave)
weHave = ourTitles[lemma] - theirTitles[lemma]
removal = " ".join(weHave)
if addition:
addition = 'addition' + ':' + addition
if removal:
removal = 'removal' + ':' + removal
if addition or removal:
sys.stdout.write(lemma)
sys.stdout.write('||')
if removal:
sys.stdout.write(removal)
if addition:
sys.stdout.write('||')
if addition:
sys.stdout.write(addition)
if addition or removal:
sys.stdout.write('\n')