0
Я кодирую игрушку PageRank, в том числе и гусеничный. Это выглядит немного странно, так как мой код не сходится к значениям PR. можно также отметить, что дельта между каждой итерации равен 0, часть продукции будет:PageRank пример игрушки не сходится
url: http://en.m.wikipedia.org/wiki/Israel_State_Cup
links_to_node: set(['http://en.m.wikipedia.org/wiki/Association_football', 'http://en.m.wikipedia.org/wiki/Wikipedia:General_disclaimer'])
links_from_node: set(['http://en.m.wikipedia.org/wiki/Israel_State_Cup'])
PR_score: 2.41759524248e+38
ttl_time: 1
last_delta: 0
Код выглядит следующим образом:
import requests
import lxml.html
import random
class pr_node:
"""WDM PR node"""
url = ""
links_to_node = set([])
links_from_node = set([])
PR_score = 0.0001
ttl_time = 0
last_delta = 0
def __init__(self, url, ttl_time):
self.url = url
self.links_to_node = set([])
self.links_from_node = set([])
self.PR_score = 0.1
self.ttl_time = ttl_time
def print_node_out_links(self):
print "\n\n" + self.url + " with ttl " + str(self.ttl_time) + " = "
s = self.links_to_node
print "{" + "\, ".join(str(e) for e in s) + "}"
def print_node_pr(self):
print "\n\n" + self.url + " PR is: " + str(self.PR_score)
def print_all(self):
print "url: " + self.url
print "links_to_node: " + repr(self.links_to_node)
print "links_from_node: " + repr(self.links_from_node)
print "PR_score: " + str(self.PR_score)
print "ttl_time: " + str(self.ttl_time)
print "last_delta: " + str(self.last_delta)
def crawl(url, url_ttl):
"""crawl to new url, if ttl == 0 max depth reached, don't visit same url twice"""
if url_ttl > 0 and (url not in visited_urls):
# create new node p from parsed page
print "crawling to " + url + "...\n"
res = requests.get(url)
doc = lxml.html.fromstring(res.content)
p = pr_node(url, url_ttl)
# add new PR node
global pr_nodes
pr_nodes[url] = p
# get all wiki links
all_links_to_node = set([])
for t in doc.xpath("//a[contains(@href, '/wiki/')]"):
add_val = ""
if not t.attrib['href'].startswith("http://") and t.attrib['href'].startswith("/wiki/"):
add_val = "http://en.m.wikipedia.org" + t.attrib['href']
all_links_to_node.add(add_val)
elif t.attrib['href'].startswith("http://"):
add_val = t.attrib['href']
all_links_to_node.add(add_val)
else:
pass
# select random 10 of them and crawl to them
iter_count = 0
iter_stop_lim = 10
while iter_count < iter_stop_lim and len(p.links_to_node) < iter_stop_lim and len(all_links_to_node) > 0:
current_url = random.sample(all_links_to_node, 1)[0]
all_links_to_node.remove(current_url) # don't do it twice...
iter_count = + 1
if not (current_url in visited_urls) and url_ttl > 1:
p.links_to_node.add(current_url)
crawl(current_url, url_ttl - 1)
visited_urls.add(url)
elif current_url in visited_urls and url_ttl == 1:
p.links_to_node.add(current_url)
else:
print "max depth reached or you've already been here"
return
def calc_graph_pr(pr_iter_count, damp_factor):
"print calculating PageRank"
current_iter = 0
global pr_nodes
g1 = {}
g2 = {}
for node in pr_nodes.itervalues():
g1[node.url] = node
g2[node.url] = node
g = [g1, g2]
while current_iter < pr_iter_count:
print "PageRank iteration #" + str(current_iter)
for p in g[current_iter % 2].itervalues():
in_links_addition = 0
for l in p.links_to_node:
l_val = g[(current_iter - 1) % 2][l]
l_val.delta = l_val.PR_score - g[current_iter % 2][l].PR_score
in_links_addition += l_val.PR_score/len(l_val.links_from_node)
p.PR_score = damp_factor + (1 - damp_factor) * in_links_addition
current_iter += 1
pr_nodes = g[0] #WLOG could be also g[1]...
for p in pr_nodes.itervalues():
p.print_all()
print "check bool:"
print g1 == g2
return
def update_graph_links():
global pr_nodes
for node in pr_nodes.itervalues():
for u in node.links_to_node:
if u in pr_nodes:
pr_nodes[u].links_from_node.add(u)
return
visited_urls = set([])
pr_nodes = {}
glob_pr_iter_count = 50
glob_damp_factor = 0.2
crawl("http://en.m.wikipedia.org/wiki/Nikola_Mitrovic", 3)
update_graph_links()
calc_graph_pr(glob_pr_iter_count, glob_damp_factor)
Так было бы просто продолжать навсегда? Я вижу, когда вычисляется дельта (разница между текущим PR-счетом и формой PR-итоговой последней итерации), но я не вижу, чтобы вы использовали это значение для любого использования. Говорят, что график, как говорят, сходится, когда дельта любого узла меньше 0,0001, должен быть некоторый код, который заканчивает итерации, когда это произойдет. – jksnw
@jksnw он еще не используется, но он демонстрирует, что в этом фрагменте кода что-то гнилое. – GalB1t