citation-map 3.4__tar.gz → 3.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {citation-map-3.4 → citation-map-3.6}/PKG-INFO +9 -4
- {citation-map-3.4 → citation-map-3.6}/README.md +8 -3
- {citation-map-3.4 → citation-map-3.6}/citation_map/citation_map.py +74 -48
- {citation-map-3.4 → citation-map-3.6}/citation_map.egg-info/PKG-INFO +9 -4
- {citation-map-3.4 → citation-map-3.6}/setup.py +1 -1
- {citation-map-3.4 → citation-map-3.6}/LICENSE.md +0 -0
- {citation-map-3.4 → citation-map-3.6}/citation_map/__init__.py +0 -0
- {citation-map-3.4 → citation-map-3.6}/citation_map.egg-info/SOURCES.txt +0 -0
- {citation-map-3.4 → citation-map-3.6}/citation_map.egg-info/dependency_links.txt +0 -0
- {citation-map-3.4 → citation-map-3.6}/citation_map.egg-info/requires.txt +0 -0
- {citation-map-3.4 → citation-map-3.6}/citation_map.egg-info/top_level.txt +0 -0
- {citation-map-3.4 → citation-map-3.6}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: citation-map
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.6
|
|
4
4
|
Summary: A simple tool to generate your Google Scholar citation world map.
|
|
5
5
|
Home-page: https://github.com/ChenLiu-1996/CitationMap
|
|
6
6
|
Author: Chen Liu
|
|
@@ -75,9 +75,14 @@ If you open it on a browser, you will see your own version of the following cita
|
|
|
75
75
|
output_path: str
|
|
76
76
|
(default is 'citation_map.html')
|
|
77
77
|
The path to the output HTML file.
|
|
78
|
-
|
|
78
|
+
num_processes_major: int
|
|
79
79
|
(default is 16)
|
|
80
|
-
Number of
|
|
80
|
+
Number of processes for parallel processing.
|
|
81
|
+
Related to `scholarly.citedby()`. Primary reason for Google Scholar bans.
|
|
82
|
+
num_processes_minor: int
|
|
83
|
+
(default is 32)
|
|
84
|
+
Number of processes for parallel processing.
|
|
85
|
+
Related to all other processes. Usually not causing problems.
|
|
81
86
|
use_proxy: bool
|
|
82
87
|
(default is False)
|
|
83
88
|
If true, we will use a scholarly proxy.
|
|
@@ -96,7 +101,7 @@ If you open it on a browser, you will see your own version of the following cita
|
|
|
96
101
|
|
|
97
102
|
- From my experience, this is a good indicator that your IP address is blocked by Google Scholar due to excessive or frequent crawling (using the `scholarly` package).
|
|
98
103
|
- One hot fix I found was to hop on a University VPN and run again. I typically experience this error after running the tool twice, and I need to disconnect and reconnect my VPN to "unblock" myself.
|
|
99
|
-
- In case
|
|
104
|
+
- In case this does not help, you can try to reduce the number of processes (e.g., setting `num_processes_major=1`).
|
|
100
105
|
|
|
101
106
|
## Changelog
|
|
102
107
|
|
|
@@ -59,9 +59,14 @@ If you open it on a browser, you will see your own version of the following cita
|
|
|
59
59
|
output_path: str
|
|
60
60
|
(default is 'citation_map.html')
|
|
61
61
|
The path to the output HTML file.
|
|
62
|
-
|
|
62
|
+
num_processes_major: int
|
|
63
63
|
(default is 16)
|
|
64
|
-
Number of
|
|
64
|
+
Number of processes for parallel processing.
|
|
65
|
+
Related to `scholarly.citedby()`. Primary reason for Google Scholar bans.
|
|
66
|
+
num_processes_minor: int
|
|
67
|
+
(default is 32)
|
|
68
|
+
Number of processes for parallel processing.
|
|
69
|
+
Related to all other processes. Usually not causing problems.
|
|
65
70
|
use_proxy: bool
|
|
66
71
|
(default is False)
|
|
67
72
|
If true, we will use a scholarly proxy.
|
|
@@ -80,7 +85,7 @@ If you open it on a browser, you will see your own version of the following cita
|
|
|
80
85
|
|
|
81
86
|
- From my experience, this is a good indicator that your IP address is blocked by Google Scholar due to excessive or frequent crawling (using the `scholarly` package).
|
|
82
87
|
- One hot fix I found was to hop on a University VPN and run again. I typically experience this error after running the tool twice, and I need to disconnect and reconnect my VPN to "unblock" myself.
|
|
83
|
-
- In case
|
|
88
|
+
- In case this does not help, you can try to reduce the number of processes (e.g., setting `num_processes_major=1`).
|
|
84
89
|
|
|
85
90
|
## Changelog
|
|
86
91
|
|
|
@@ -6,6 +6,7 @@ import itertools
|
|
|
6
6
|
from typing import List, Tuple
|
|
7
7
|
from scholarly import scholarly, ProxyGenerator
|
|
8
8
|
from geopy.geocoders import Nominatim
|
|
9
|
+
|
|
9
10
|
import folium
|
|
10
11
|
from tqdm import tqdm
|
|
11
12
|
from multiprocessing import Pool
|
|
@@ -19,51 +20,52 @@ def fetch_google_scholar_profile(scholar_id: str):
|
|
|
19
20
|
author = scholarly.fill(author, sections=['publications'])
|
|
20
21
|
return author
|
|
21
22
|
|
|
22
|
-
def find_all_citing_institutions(publications,
|
|
23
|
+
def find_all_citing_institutions(publications, num_processes_major: int = 16, num_processes_minor: int = 32) -> List[Tuple[str]]:
|
|
23
24
|
'''
|
|
24
25
|
Step 2. Final all citing institutions (i.e., insitutions of citing authors).
|
|
25
26
|
'''
|
|
26
|
-
if
|
|
27
|
+
if num_processes_minor > 1 and isinstance(num_processes_minor, int):
|
|
27
28
|
# Fetch metadata for all publications, in parallel.
|
|
28
|
-
with Pool(processes=
|
|
29
|
+
with Pool(processes=num_processes_minor) as pool:
|
|
29
30
|
all_publications = list(tqdm(pool.imap(__fill_publication_metadata, publications),
|
|
30
31
|
desc='Filling metadata for all publications...',
|
|
31
32
|
total=len(publications)))
|
|
32
|
-
|
|
33
|
-
# Find all citing papers from all publications, in parallel.
|
|
34
|
-
with Pool(processes=num_processes) as pool:
|
|
35
|
-
all_citing_papers_nested = list(tqdm(pool.imap(__citing_papers_from_publication, all_publications),
|
|
36
|
-
desc='Finding all citations...',
|
|
37
|
-
total=len(all_publications)))
|
|
38
|
-
all_citing_papers = list(itertools.chain(*all_citing_papers_nested))
|
|
39
|
-
|
|
40
|
-
# Find all citing authors from all citing papers, in parallel.
|
|
41
|
-
with Pool(processes=num_processes) as pool:
|
|
42
|
-
all_citing_authors_nested = list(tqdm(pool.imap(__authors_from_papers, all_citing_papers),
|
|
43
|
-
desc='Finding all citing authors...',
|
|
44
|
-
total=len(all_citing_papers)))
|
|
45
|
-
all_citing_authors = list(itertools.chain(*all_citing_authors_nested))
|
|
46
|
-
|
|
47
|
-
# Find all citing insitutions from all citing authors, in parallel.
|
|
48
|
-
with Pool(processes=num_processes) as pool:
|
|
49
|
-
author_institution_tuple_list = list(tqdm(pool.imap(__institutions_from_authors, all_citing_authors),
|
|
50
|
-
desc='Finding all citing institutions...',
|
|
51
|
-
total=len(all_citing_authors)))
|
|
52
33
|
else:
|
|
53
34
|
all_publications = []
|
|
54
35
|
for pub in tqdm(publications, desc='Filling metadata for all publications...', total=len(publications)):
|
|
55
36
|
all_publications.append(__fill_publication_metadata(pub))
|
|
56
37
|
|
|
38
|
+
if num_processes_major > 1 and isinstance(num_processes_major, int):
|
|
39
|
+
# Find all citing papers from all publications, in parallel.
|
|
40
|
+
with Pool(processes=num_processes_major) as pool:
|
|
41
|
+
all_citing_papers_nested = list(tqdm(pool.imap(__citing_papers_from_publication, all_publications),
|
|
42
|
+
desc='Finding all citations...',
|
|
43
|
+
total=len(all_publications)))
|
|
44
|
+
else:
|
|
57
45
|
all_citing_papers_nested = []
|
|
58
46
|
for pub in tqdm(all_publications, desc='Finding all citations...', total=len(all_publications)):
|
|
59
|
-
all_citing_papers_nested.append(
|
|
60
|
-
|
|
47
|
+
all_citing_papers_nested.append(__citing_papers_from_publication_difficult(pub))
|
|
48
|
+
all_citing_papers = list(itertools.chain(*all_citing_papers_nested))
|
|
61
49
|
|
|
50
|
+
if num_processes_minor > 1 and isinstance(num_processes_minor, int):
|
|
51
|
+
# Find all citing authors from all citing papers, in parallel.
|
|
52
|
+
with Pool(processes=num_processes_minor) as pool:
|
|
53
|
+
all_citing_authors_nested = list(tqdm(pool.imap(__authors_from_papers, all_citing_papers),
|
|
54
|
+
desc='Finding all citing authors...',
|
|
55
|
+
total=len(all_citing_papers)))
|
|
56
|
+
else:
|
|
62
57
|
all_citing_authors_nested = []
|
|
63
58
|
for paper in tqdm(all_citing_papers, desc='Finding all citing authors...', total=len(all_citing_papers)):
|
|
64
59
|
all_citing_authors_nested.append(__authors_from_papers(paper))
|
|
65
|
-
|
|
60
|
+
all_citing_authors = list(itertools.chain(*all_citing_authors_nested))
|
|
66
61
|
|
|
62
|
+
if num_processes_minor > 1 and isinstance(num_processes_minor, int):
|
|
63
|
+
# Find all citing insitutions from all citing authors, in parallel.
|
|
64
|
+
with Pool(processes=num_processes_minor) as pool:
|
|
65
|
+
author_institution_tuple_list = list(tqdm(pool.imap(__institutions_from_authors, all_citing_authors),
|
|
66
|
+
desc='Finding all citing institutions...',
|
|
67
|
+
total=len(all_citing_authors)))
|
|
68
|
+
else:
|
|
67
69
|
author_institution_tuple_list = []
|
|
68
70
|
for author in tqdm(all_citing_authors, desc='Finding all citing institutions...', total=len(all_citing_authors)):
|
|
69
71
|
author_institution_tuple_list.append(__institutions_from_authors(author))
|
|
@@ -91,12 +93,12 @@ def clean_institution_names(author_institution_tuple_list: List[Tuple[str]]) ->
|
|
|
91
93
|
cleaned_author_institution_tuple_list.append((author_name, cleaned_institution))
|
|
92
94
|
return cleaned_author_institution_tuple_list
|
|
93
95
|
|
|
94
|
-
def institution_text_to_geocode(author_institution_tuple_list: List[Tuple[str]],
|
|
96
|
+
def institution_text_to_geocode(author_institution_tuple_list: List[Tuple[str]], num_processes_minor: int = 32) -> List[Tuple[str]]:
|
|
95
97
|
'''
|
|
96
98
|
Step 4: Convert institutions in plain text to Geocode.
|
|
97
99
|
'''
|
|
98
|
-
if
|
|
99
|
-
with Pool(processes=
|
|
100
|
+
if num_processes_minor > 1 and isinstance(num_processes_minor, int):
|
|
101
|
+
with Pool(processes=num_processes_minor) as pool:
|
|
100
102
|
coordinates = list(tqdm(pool.imap(__text_to_geocode, author_institution_tuple_list),
|
|
101
103
|
desc='Finding all geographic coordinates...',
|
|
102
104
|
total=len(author_institution_tuple_list)))
|
|
@@ -134,10 +136,23 @@ def __fill_publication_metadata(pub):
|
|
|
134
136
|
|
|
135
137
|
def __citing_papers_from_publication(pub):
|
|
136
138
|
if 'citedby_url' in pub:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return
|
|
139
|
+
time.sleep(random.uniform(1, 5)) # Random delay to reduce risk of being blocked.
|
|
140
|
+
citing_paper_iterator = scholarly.citedby(pub)
|
|
141
|
+
citing_paper_list = [item for item in citing_paper_iterator]
|
|
142
|
+
return citing_paper_list
|
|
143
|
+
return []
|
|
144
|
+
|
|
145
|
+
def __citing_papers_from_publication_difficult(pub):
|
|
146
|
+
if 'citedby_url' in pub:
|
|
147
|
+
time.sleep(random.uniform(1, 5)) # Random delay to reduce risk of being blocked.
|
|
148
|
+
citing_paper_iterator = scholarly.citedby(pub)
|
|
149
|
+
citing_paper_list = []
|
|
150
|
+
# Unpacking the iterator to a list invokes `scholarly`,
|
|
151
|
+
# which can easily get us blocked if not handled carefully.
|
|
152
|
+
for item in citing_paper_iterator:
|
|
153
|
+
time.sleep(random.uniform(1, 2)) # Random delay to reduce risk of being blocked.
|
|
154
|
+
citing_paper_list.append(item)
|
|
155
|
+
return citing_paper_list
|
|
141
156
|
return []
|
|
142
157
|
|
|
143
158
|
def __authors_from_papers(citing_paper):
|
|
@@ -155,19 +170,22 @@ def __institutions_from_authors(author_id):
|
|
|
155
170
|
return (citing_author['name'], citing_author['affiliation'])
|
|
156
171
|
return []
|
|
157
172
|
|
|
158
|
-
def __text_to_geocode(author_institution_tuple):
|
|
173
|
+
def __text_to_geocode(author_institution_tuple, max_attempts: int = 2):
|
|
159
174
|
geolocator = Nominatim(user_agent='citation_mapper')
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
175
|
+
for _ in range(max_attempts):
|
|
176
|
+
try:
|
|
177
|
+
author_name, institution_name = author_institution_tuple
|
|
178
|
+
geo_location = geolocator.geocode(institution_name)
|
|
179
|
+
if geo_location:
|
|
180
|
+
return (geo_location.latitude, geo_location.longitude, author_name, institution_name)
|
|
181
|
+
except:
|
|
182
|
+
pass
|
|
183
|
+
return None
|
|
167
184
|
|
|
168
185
|
def generate_citation_map(scholar_id: str,
|
|
169
186
|
output_path: str = 'citation_map.html',
|
|
170
|
-
|
|
187
|
+
num_processes_major: int = 16,
|
|
188
|
+
num_processes_minor: int = 32,
|
|
171
189
|
use_proxy: bool = False,
|
|
172
190
|
pin_colorful: bool = True,
|
|
173
191
|
print_citing_institutions: bool = True):
|
|
@@ -181,9 +199,14 @@ def generate_citation_map(scholar_id: str,
|
|
|
181
199
|
output_path: str
|
|
182
200
|
(default is 'citation_map.html')
|
|
183
201
|
The path to the output HTML file.
|
|
184
|
-
|
|
202
|
+
num_processes_major: int
|
|
185
203
|
(default is 16)
|
|
186
|
-
Number of
|
|
204
|
+
Number of processes for parallel processing.
|
|
205
|
+
Related to `scholarly.citedby()`. Primary reason for Google Scholar bans.
|
|
206
|
+
num_processes_minor: int
|
|
207
|
+
(default is 32)
|
|
208
|
+
Number of processes for parallel processing.
|
|
209
|
+
Related to all other processes. Usually not causing problems.
|
|
187
210
|
use_proxy: bool
|
|
188
211
|
(default is False)
|
|
189
212
|
If true, we will use a scholarly proxy.
|
|
@@ -206,7 +229,9 @@ def generate_citation_map(scholar_id: str,
|
|
|
206
229
|
author_profile = fetch_google_scholar_profile(scholar_id)
|
|
207
230
|
print('\nAuthor profile found, with %d publications.\n' % len(author_profile['publications']))
|
|
208
231
|
|
|
209
|
-
author_institution_tuple_list = find_all_citing_institutions(author_profile['publications'],
|
|
232
|
+
author_institution_tuple_list = find_all_citing_institutions(author_profile['publications'],
|
|
233
|
+
num_processes_major=num_processes_major,
|
|
234
|
+
num_processes_minor=num_processes_minor)
|
|
210
235
|
print('\nA total of %d citing institutions recorded.\n' % len(author_institution_tuple_list))
|
|
211
236
|
|
|
212
237
|
if print_citing_institutions:
|
|
@@ -221,8 +246,9 @@ def generate_citation_map(scholar_id: str,
|
|
|
221
246
|
for item in sorted(cleaned_author_institution_tuple_list):
|
|
222
247
|
print(item)
|
|
223
248
|
|
|
224
|
-
coordinates = institution_text_to_geocode(author_institution_tuple_list + cleaned_author_institution_tuple_list,
|
|
225
|
-
|
|
249
|
+
coordinates = institution_text_to_geocode(author_institution_tuple_list + cleaned_author_institution_tuple_list,
|
|
250
|
+
num_processes_minor=num_processes_minor)
|
|
251
|
+
print('\nConverted the institutions to %d Geocodes.' % len(coordinates))
|
|
226
252
|
|
|
227
253
|
citation_map = create_map(coordinates, pin_colorful=pin_colorful)
|
|
228
254
|
citation_map.save(output_path)
|
|
@@ -234,4 +260,4 @@ if __name__ == '__main__':
|
|
|
234
260
|
# Replace this with your Google Scholar ID.
|
|
235
261
|
scholar_id = '3rDjnykAAAAJ'
|
|
236
262
|
generate_citation_map(scholar_id, output_path='citation_map.html',
|
|
237
|
-
|
|
263
|
+
num_processes_minor=16, use_proxy=False, pin_colorful=True, print_citing_institutions=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: citation-map
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.6
|
|
4
4
|
Summary: A simple tool to generate your Google Scholar citation world map.
|
|
5
5
|
Home-page: https://github.com/ChenLiu-1996/CitationMap
|
|
6
6
|
Author: Chen Liu
|
|
@@ -75,9 +75,14 @@ If you open it on a browser, you will see your own version of the following cita
|
|
|
75
75
|
output_path: str
|
|
76
76
|
(default is 'citation_map.html')
|
|
77
77
|
The path to the output HTML file.
|
|
78
|
-
|
|
78
|
+
num_processes_major: int
|
|
79
79
|
(default is 16)
|
|
80
|
-
Number of
|
|
80
|
+
Number of processes for parallel processing.
|
|
81
|
+
Related to `scholarly.citedby()`. Primary reason for Google Scholar bans.
|
|
82
|
+
num_processes_minor: int
|
|
83
|
+
(default is 32)
|
|
84
|
+
Number of processes for parallel processing.
|
|
85
|
+
Related to all other processes. Usually not causing problems.
|
|
81
86
|
use_proxy: bool
|
|
82
87
|
(default is False)
|
|
83
88
|
If true, we will use a scholarly proxy.
|
|
@@ -96,7 +101,7 @@ If you open it on a browser, you will see your own version of the following cita
|
|
|
96
101
|
|
|
97
102
|
- From my experience, this is a good indicator that your IP address is blocked by Google Scholar due to excessive or frequent crawling (using the `scholarly` package).
|
|
98
103
|
- One hot fix I found was to hop on a University VPN and run again. I typically experience this error after running the tool twice, and I need to disconnect and reconnect my VPN to "unblock" myself.
|
|
99
|
-
- In case
|
|
104
|
+
- In case this does not help, you can try to reduce the number of processes (e.g., setting `num_processes_major=1`).
|
|
100
105
|
|
|
101
106
|
## Changelog
|
|
102
107
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|