-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexplore.py
More file actions
203 lines (176 loc) · 6.43 KB
/
Copy pathexplore.py
File metadata and controls
203 lines (176 loc) · 6.43 KB
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
from collections import deque
from db import duckdb_connect, sqlite_connect
def shortest_path(source_title, target_title):
with sqlite_connect() as connection:
def get_id(title):
row = connection.execute(
"SELECT id FROM internal_pages WHERE ns = 0 AND title = ?", (title,)
).fetchone()
return row[0] if row else None
def get_title(page_id):
row = connection.execute(
"SELECT title FROM internal_pages WHERE id = ?", (page_id,)
).fetchone()
return row[0] if row else None
def get_neighbours(page_id):
return [
row[0]
for row in connection.execute(
"SELECT target_id FROM internal_links WHERE source_id = ?",
(page_id,),
).fetchall()
]
source_id = get_id(source_title)
target_id = get_id(target_title)
if not source_id:
return {"error": f"Page not found: '{source_title}'"}
if not target_id:
return {"error": f"Page not found: '{target_title}'"}
queue = deque([[source_id]])
visited = {source_id}
while queue:
path = queue.popleft()
current = path[-1]
if current == target_id:
return {
"path": [get_title(pid) for pid in path],
"hops": len(path) - 1,
}
for neighbour in get_neighbours(current):
if neighbour not in visited:
visited.add(neighbour)
queue.append(path + [neighbour])
return {"error": "No path found."}
def redirect_statistics():
with duckdb_connect() as connection:
total = connection.execute("SELECT COUNT(*) FROM internal_pages").fetchone()[0]
content_and_redirects = connection.execute(
"SELECT COUNT(*) FROM internal_pages WHERE ns = 0"
).fetchone()[0]
categories = connection.execute(
"SELECT COUNT(*) FROM internal_pages WHERE ns = 14"
).fetchone()[0]
redirects = connection.execute("SELECT COUNT(*) FROM redirects").fetchone()[0]
content = content_and_redirects - redirects
return {
"total": total,
"content": content,
"categories": categories,
"redirects": redirects,
}
def degree_distribution():
with duckdb_connect() as connection:
result = {}
for degree_column in ("in_degree", "out_degree"):
rows = connection.execute(
f"""
SELECT
CASE
WHEN {degree_column} = 0 THEN '0'
WHEN {degree_column} < 5 THEN '1-4'
WHEN {degree_column} < 10 THEN '5-9'
WHEN {degree_column} < 50 THEN '10-49'
WHEN {degree_column} < 100 THEN '50-99'
WHEN {degree_column} < 500 THEN '100-499'
ELSE '500+'
END AS bucket,
COUNT(*) AS pages
FROM internal_pages
WHERE ns = 0
GROUP BY bucket
ORDER BY MIN({degree_column})
"""
).fetchall()
result[degree_column] = [
{"bucket": bucket, "pages": pages} for bucket, pages in rows
]
return result
def top_pages_by_pagerank(ns, limit=100):
with duckdb_connect() as connection:
rows = connection.execute(
"""
SELECT title, rank1
FROM internal_pages
WHERE ns = ?
ORDER BY rank1 DESC
LIMIT ?
""",
(ns, limit),
).fetchall()
return [
{"rank": i, "title": title, "score": score}
for i, (title, score) in enumerate(rows, 1)
]
def domain_authority(min_citing_pages=10, limit=100):
with duckdb_connect() as connection:
rows = connection.execute(
"""
SELECT *
FROM external_domain_authority
WHERE citing_pages >= ?
ORDER BY total_citing_pagerank DESC
LIMIT ?
""",
(min_citing_pages, limit),
).fetchall()
return [
{
"domain": name,
"tld": tld,
"citing_pages": citing_pages,
"avg_citing_pagerank": avg_citing_pagerank,
"total_citing_pagerank": total_citing_pagerank,
}
for domain_id, name, tld, citing_pages, avg_citing_pagerank, total_citing_pagerank in rows
]
def page_source_profile(title, min_citations=1):
with duckdb_connect() as connection:
rows = connection.execute(
"""
SELECT *
FROM internal_page_profile
WHERE ns = 0 AND title = ? AND domain_citation_count >= ?
ORDER BY domain_citation_count DESC, domain
""",
(title, min_citations),
).fetchall()
return [
{
"url": url,
"domain": domain,
"tld": tld,
"domain_citation_count": domain_citation_count,
}
for page_id, ns, title, url, domain, tld, domain_citation_count in rows
]
def tld_authority(min_citing_pages=1000):
with duckdb_connect() as connection:
rows = connection.execute(
"""
SELECT *
FROM tld_authority
WHERE citing_pages >= ?
ORDER BY total_citing_pagerank DESC
""",
(min_citing_pages,),
).fetchall()
return [
{
"tld": tld,
"domains": domains,
"citing_pages": citing_pages,
"avg_citing_pagerank": avg_citing_pagerank,
"total_citing_pagerank": total_citing_pagerank,
}
for tld, domains, citing_pages, avg_citing_pagerank, total_citing_pagerank in rows
]
if __name__ == "__main__":
from pprint import pprint
pprint(shortest_path("Mathematics", "Adolf Hitler"))
pprint(degree_distribution())
pprint(redirect_statistics())
pprint(top_pages_by_pagerank(0))
pprint(top_pages_by_pagerank(14))
pprint(domain_authority())
pprint(page_source_profile("Mathematics"))
pprint(tld_authority())