]> code.communitydata.science - wikia_userroles_scraper.git/blob - userroles_from_logevents.py
Initialize the repository for the wikia user roles scraper project.
[wikia_userroles_scraper.git] / userroles_from_logevents.py
1 #!/usr/bin/env python3
2 from os import path
3 import argparse
4 import time
5 import re
6 import os
7 from json.decoder import JSONDecodeError
8 from scraper_utils import prepare_output, read_wikilist, add_parser_arguments
9 import requests
10
11
12 def write_logevents(logevents, out):
13     for logevent in logevents:
14         # if there is hidden information, we skip this one because there
15         # is nothing to report
16         if any(['userhidden' in logevent,
17                 'actionhidden' in logevent,
18                 'commenthidden' in logevent]):
19             continue
20
21         le_output = [logevent['comment'],
22                      str(logevent['logid']),
23                      str(logevent['ns']),
24                      str(logevent['pageid']),
25                      logevent['timestamp'],
26                      logevent['title'],
27                      logevent['type'],
28                      str(logevent['user'])]
29
30         if "rights" in logevent:
31             le_output.extend(['false',
32                               logevent['rights']['new'],
33                               logevent['rights']['old']])
34         else:
35             le_output.extend(['true', '', ''])
36
37         out.write("\t".join(le_output) + "\n")
38     out.flush()
39     # output data
40
41
42 def write_blockevents(logevents, out):
43     for logevent in logevents:
44         # if there is hidden information, we skip this one because there
45         # is nothing to report
46         if any(['userhidden' in logevent,
47                 'actionhidden' in logevent,
48                 'commenthidden' in logevent]):
49             continue
50
51         le_output = [logevent['comment'],
52                      str(logevent['logid']),
53                      str(logevent['ns']),
54                      str(logevent['pageid']),
55                      logevent['timestamp'],
56                      logevent['title'],
57                      logevent['type'],
58                      str(logevent['user'])]
59
60         if "rights" in logevent:
61             le_output.extend(['false',
62                               logevent['rights']['new'],
63                               logevent['rights']['old']])
64         else:
65             le_output.extend(['true', '', ''])
66
67         out.write("\t".join(le_output) + "\n")
68     out.flush()
69     # output data
70
71
72 def get_events_for_wiki(wikiname, url, output_dir, blocks_output=None, wikitype="wikia"):
73     out = open("{0}/{1}.tsv".format(output_dir, wikiname), "w")
74
75     out.write("\t".join(['comment', 'logid', 'ns', 'pageid', 'timestamp',
76                          'title', 'type', 'user', 'ancient', 'rights-new',
77                          'rights-old\n']))
78
79     if wikitype == "wikia":
80         api_url = url + '/api.php'
81     else:  # wikitype == wikipedia
82         api_url = url + "/w/api.php"
83
84     letype = 'rights'
85
86     if blocks_output is not None:
87         letype = 'rights|block|unblock'
88         blockout = open("{0}/{1}.tsv".format(blocks_output, wikiname), "w")
89         blockout.write("\t".join(['comment', 'logid', 'ns', 'pageid', 'timestamp',
90                                   'title', 'type', 'user', 'ancient', 'rights-new',
91                                   'rights-old\n']))
92
93     query = {'action': 'query',
94              'list': 'logevents',
95              'letype': letype,
96              'lelimit': '500',
97              'format': 'json',
98              'ledir': 'newer'}
99
100     try:
101         response = requests.get(api_url, params=query)
102         rv = response.json()
103
104     except (JSONDecodeError):
105         api_url = response.url
106         # print api_url # debug
107         if wikitype == "wikia":
108             re_str = "^http://(community|www).wikia.com/"
109         else:  # wikitype == "wikipedia"
110             re_str = "^(http|https)://.*wikipedia.org/"
111
112         if re.match(re_str, api_url):
113             # api_url
114             # 'http://community.wikia.com/wiki/Community_Central:Not_a_valid_Wikia':
115             print("ERROR: %s no longer exists" % wikiname)
116             return
117         else:
118             response = requests.get(api_url, params=query)
119             rv = response.json()
120
121     try:
122         logevents = rv['query']['logevents']
123
124         blockevents = [e for e in logevents
125                        if (e['action'] in ['block', 'unblock'])
126                        or (e['type'] in ['block', 'unblock'])]
127
128         logevents = [e for e in logevents if e not in blockevents]
129
130         write_logevents(logevents, out)
131
132         write_blockevents(blockevents, blockout)
133
134     except KeyError:
135         print("ERROR: %s contains no logevent data" % wikiname)
136         return
137
138     while 'query-continue' in rv or 'continue' in rv:
139         if 'query-continue' in rv:
140             query['lestart'] = rv['query-continue']['logevents']['lestart']
141         else:
142             query['continue'] = str(rv['continue'])
143             query['lecontinue'] = str(rv['continue']['lecontinue'])
144
145         response = requests.get(api_url, params=query)
146         rv = response.json()
147         logevents = rv['query']['logevents']
148         write_logevents(logevents, out)
149
150     out.close()
151
152
153 # the call is
154 # %run userroles_from_logevents.py --sep=\\t --nuke-old --blocks-output=/com/projects/messagewalls/userroles/blockevents ../identifyWikis/wikiteamWikilist.tsv /com/projects/messagewalls/userroles/listusers
155 if __name__ == '__main__':
156     parser = argparse.ArgumentParser(
157         description="Get user roles for Wikis from the Mediawiki list users API")
158
159     parser = add_parser_arguments(parser)
160
161     parser.add_argument('--blocks-output',
162                         type=str,
163                         help='Path to output block event logs. If empty, blocks are ignored.'
164                         )
165
166     args = parser.parse_args()
167     output_path = args.output
168     blocks_output = args.blocks_output
169     header = not args.no_header
170
171     prepare_output(output_path, args.nuke_old)
172
173     if blocks_output is not None:
174         prepare_output(blocks_output, args.nuke_old)
175
176     wikilist = read_wikilist(args)
177     deleted = []
178     notauthorized = []
179
180     files = [os.path.join(output_path, i) for i in os.listdir(output_path)]
181
182     # interate through the list of wikis
183     # for line in ["anime,http://anime.wikia.com/"]:
184     # for line in ["blogging,http://blogging.wikia.com/"]:
185     wikilist = read_wikilist(args)
186
187     # for line in open("list_of_wikis.csv", "r").readlines():
188
189     for wiki, url, wikitype in wikilist:
190         if "{0}.{1}".format(path.join(output_path, wiki), 'tsv') in files:
191             print("SKIPPING: file \"%s\" already exists)" % wiki)
192             continue
193
194         if wiki in files:
195             print("SKIPPING: file \"%s\" already exists)" % wiki)
196             continue
197
198         print("Processing wiki: %s" % wiki)
199         get_events_for_wiki(
200             wiki,
201             url,
202             output_dir=output_path,
203             blocks_output=blocks_output,
204             wikitype=wikitype)
205
206         time.sleep(1)

Community Data Science Collective || Want to submit a patch?