-
Notifications
You must be signed in to change notification settings - Fork 11
/
wikirandom.py
executable file
·123 lines (111 loc) · 4.74 KB
/
wikirandom.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# wikirandom.py: Functions for downloading random articles from Wikipedia
#
# Copyright (C) 2010 Matthew D. Hoffman
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys, urllib2, re, string, time, threading
def get_random_wikipedia_article():
"""
Downloads a randomly selected Wikipedia article (via
http://en.wikipedia.org/wiki/Special:Random) and strips out (most
of) the formatting, links, etc.
This function is a bit simpler and less robust than the code that
was used for the experiments in "Online VB for LDA."
"""
failed = True
timeout = 1
while failed:
articletitle = None
failed = False
try:
req = urllib2.Request('http://en.wikipedia.org/wiki/Special:Random',
None, { 'User-Agent' : 'x'})
f = urllib2.urlopen(req)
while not articletitle:
line = f.readline()
result = re.search(r'title="Edit this page" href="/w/index.php\?title=(.*)\&action=edit" /\>', line)
if (result):
articletitle = result.group(1)
break
elif (len(line) < 1):
sys.exit(1)
req = urllib2.Request('http://en.wikipedia.org/w/index.php?title=Special:Export/%s&action=submit' \
% (articletitle),
None, { 'User-Agent' : 'x'})
f = urllib2.urlopen(req, timeout=timeout)
all = f.read()
except:# (urllib2.HTTPError, urllib2.URLError):
timeout *= 2
print 'oops. there was a failure downloading %s. retrying...' \
% articletitle
failed = True
continue
print 'downloaded %s. parsing...' % articletitle
try:
all = re.search(r'<text.*?>(.*)</text', all, flags=re.DOTALL).group(1)
all = re.sub(r'\n', ' ', all)
all = re.sub(r'\{\{.*?\}\}', r'', all)
all = re.sub(r'\[\[Category:.*', '', all)
all = re.sub(r'==\s*[Ss]ource\s*==.*', '', all)
all = re.sub(r'==\s*[Rr]eferences\s*==.*', '', all)
all = re.sub(r'==\s*[Ee]xternal [Ll]inks\s*==.*', '', all)
all = re.sub(r'==\s*[Ee]xternal [Ll]inks and [Rr]eferences==\s*', '', all)
all = re.sub(r'==\s*[Ss]ee [Aa]lso\s*==.*', '', all)
all = re.sub(r'http://[^\s]*', '', all)
all = re.sub(r'\[\[Image:.*?\]\]', '', all)
all = re.sub(r'Image:.*?\|', '', all)
all = re.sub(r'\[\[.*?\|*([^\|]*?)\]\]', r'\1', all)
all = re.sub(r'\<.*?>', '', all)
except:
# Something went wrong, try again. (This is bad coding practice.)
print 'oops. there was a failure parsing %s. retrying...' \
% articletitle
failed = True
continue
return(all, articletitle)
class WikiThread(threading.Thread):
articles = list()
articlenames = list()
lock = threading.Lock()
def run(self):
(article, articlename) = get_random_wikipedia_article()
WikiThread.lock.acquire()
WikiThread.articles.append(article)
WikiThread.articlenames.append(articlename)
WikiThread.lock.release()
def get_random_wikipedia_articles(n):
"""
Downloads n articles in parallel from Wikipedia and returns lists
of their names and contents. Much faster than calling
get_random_wikipedia_article() serially.
"""
maxthreads = 8
WikiThread.articles = list()
WikiThread.articlenames = list()
wtlist = list()
for i in range(0, n, maxthreads):
print 'downloaded %d/%d articles...' % (i, n)
for j in range(i, min(i+maxthreads, n)):
wtlist.append(WikiThread())
wtlist[len(wtlist)-1].start()
for j in range(i, min(i+maxthreads, n)):
wtlist[j].join()
return (WikiThread.articles, WikiThread.articlenames)
if __name__ == '__main__':
t0 = time.time()
(articles, articlenames) = get_random_wikipedia_articles(1)
for i in range(0, len(articles)):
print articlenames[i]
t1 = time.time()
print 'took %f' % (t1 - t0)