Я считаю, что большая часть времени тратится на эти SQL-запросы:
for (urlid,) in self.con.execute("select rowid from urllist"):
...
for (inlink,) in self.con.execute("select distinct fromid from link where toid=%d" % urlid):
...
numoutlinks[urlid]=self.con.execute("select count(*) from link where fromid=%d" % urlid).fetchone()[0]
Если у вас достаточно памяти, вы можете сократить это до двух запросов:
SELECT fromid,toid FROM link WHERE toid IN (SELECT rowid FROM urllist)
а также
SELECT fromid,count(*) FROM link WHERE fromid IN (SELECT rowid FROM urllist) GROUP BY fromid
Затем вы можете просмотреть результаты и построить inlinks
, numoutlinks
и pagerank
.
Вы также можете воспользоваться collections.defaultdict
:
import collections
import itertools
def constant_factory(value):
return itertools.repeat(value).next
Следующее затем делает inlinks
диктом сетов. Наборы уместны, т.к.
Вы хотите только отдельные URL
inlinks=collections.defaultdict(set)
И это делает pagerank
диктовкой со значением по умолчанию 1,0:
pagerank=collections.defaultdict(constant_factory(1.0))
Преимущество использования collection.defaultdict в том, что вы
не нужно предварительно инициализировать диктовку.
Итак, все, что я предлагаю, выглядело бы примерно так:
import collections
def constant_factory(value):
return itertools.repeat(value).next
def calculatepagerank2(self,iterations=20):
# clear out the current PageRank tables
self.con.execute("DROP TABLE IF EXISTS pagerank")
self.con.execute("CREATE TABLE pagerank(urlid primary key,score)")
self.con.execute("CREATE INDEX prankidx ON pagerank(urlid)")
# initialize every url with a PageRank of 1.0
self.con.execute("INSERT INTO pagerank SELECT rowid,1.0 FROM urllist")
self.dbcommit()
inlinks=collections.defaultdict(set)
sql='''SELECT fromid,toid FROM link WHERE toid IN (SELECT rowid FROM urllist)'''
for f,t in self.con.execute(sql):
inlinks[t].add(f)
numoutlinks={}
sql='''SELECT fromid,count(*) FROM link WHERE fromid IN (SELECT rowid FROM urllist) GROUP BY fromid'''
for f,c in self.con.execute(sql):
numoutlinks[f]=c
pagerank=collections.defaultdict(constant_factory(1.0))
for i in range(iterations):
print "Iteration %d" % i
for urlid in inlinks:
pr=0.15
for link in inlinks[urlid]:
linkpr=pagerank[link]
linkcount=numoutlinks[link]
pr+=0.85*(linkpr/linkcount)
pagerank[urlid]=pr
sql="UPDATE pagerank SET score=? WHERE urlid=?"
args=((pagerank[urlid],urlid) for urlid in pagerank)
self.con.executemany(sql, args)
self.dbcommit()