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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: citation-map
3
- Version: 3.4
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
- num_processes: int
78
+ num_processes_major: int
79
79
  (default is 16)
80
- Number of separate processes for parallel processing.
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 changing your IP address does not help, you can try to reduce the number of processes (e.g., setting `num_processes=1`).
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
- num_processes: int
62
+ num_processes_major: int
63
63
  (default is 16)
64
- Number of separate processes for parallel processing.
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 changing your IP address does not help, you can try to reduce the number of processes (e.g., setting `num_processes=1`).
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, num_processes: int = 16) -> List[Tuple[str]]:
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 num_processes > 1 and isinstance(num_processes, int):
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=num_processes) as pool:
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(__citing_papers_from_publication(pub))
60
- all_citing_papers = list(itertools.chain(*all_citing_papers_nested))
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
- all_citing_authors = list(itertools.chain(*all_citing_authors_nested))
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]], num_processes: int = 16) -> 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 num_processes > 1 and isinstance(num_processes, int):
99
- with Pool(processes=num_processes) as pool:
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
- # time.sleep(random.uniform(1, 5)) # Random delay to reduce risk of being blocked.
138
- citing_paper_obj = scholarly.citedby(pub)
139
- # time.sleep(random.uniform(1, 5)) # Random delay to reduce risk of being blocked.
140
- return [item for item in citing_paper_obj]
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
- try:
161
- author_name, institution_name = author_institution_tuple
162
- geo_location = geolocator.geocode(institution_name)
163
- if geo_location:
164
- return (geo_location.latitude, geo_location.longitude, author_name, institution_name)
165
- except:
166
- return None
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
- num_processes: int = 16,
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
- num_processes: int
202
+ num_processes_major: int
185
203
  (default is 16)
186
- Number of separate processes for parallel processing.
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'], num_processes=num_processes)
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, num_processes=num_processes)
225
- print('\nConverted the institutions to Geocodes.')
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
- num_processes=16, use_proxy=False, pin_colorful=True, print_citing_institutions=True)
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.4
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
- num_processes: int
78
+ num_processes_major: int
79
79
  (default is 16)
80
- Number of separate processes for parallel processing.
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 changing your IP address does not help, you can try to reduce the number of processes (e.g., setting `num_processes=1`).
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
 
@@ -5,7 +5,7 @@ with open('README.md') as f:
5
5
 
6
6
  setup(
7
7
  name='citation-map',
8
- version='3.4',
8
+ version='3.6',
9
9
  license='Apache 2.0',
10
10
  author='Chen Liu',
11
11
  author_email='chen.liu.cl2482@yale.edu',
File without changes
File without changes