citation-map 2.0__tar.gz → 3.0__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: 2.0
3
+ Version: 3.0
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
@@ -39,8 +39,6 @@ If you open it on a browser, you will see your own version of the following cita
39
39
 
40
40
  <img src = "assets/citation_world_map.png" width=800>
41
41
 
42
- ## News
43
- `citation-map` has been upgraded to version 2.0! I finally managed to drastically speed up the process using multiprocessing (without being blocked by Google Scholar). On my personal computer, processing my profile with 100 citations took 1 hour with version 1.0 while it's now taking 5 minutes with version 2.0.
44
42
 
45
43
  ## Usage
46
44
  1. Install the package.
@@ -88,6 +86,27 @@ If you open it on a browser, you will see your own version of the following cita
88
86
  If true, print the list of citing institutions (affiliations of citing authors).
89
87
  ```
90
88
 
89
+ ## Changelog
90
+
91
+ ### Version 3.0
92
+ I realized a problem with how I used `geopy.geocoders`. A majority of the authors' self-entered affiliations are not successfully found in the system and hence are not converted to geographic coordinates on the world map. For example, the string "Yale University" is a much better entry than "Assistant Professor at Yale University".
93
+
94
+ I applied a simple fix with some rule-based language processing. This helps us identify many missing citing locations.
95
+
96
+ ### Version 2.0
97
+ I finally managed to **drastically speed up** the process using multiprocessing, in a way that avoids being blocked by Google Scholar.
98
+
99
+ On my personal computer, processing my profile with 100 citations took 1 hour with version 1.0 while it's now taking 5 minutes with version 2.0.
100
+
101
+ With that said, please be careful and do not run this tool frequently. I can easily get on Google Scholar's blacklist after a few runs.
102
+
103
+ ### Version 1.0
104
+ Very basic functionality.
105
+
106
+ This script is a bit slow. On my personal computer, it takes half a minute to process each citation. If you have thousands of citations, it may or may not be a good idea to use this script.
107
+
108
+ I tried to use multiprocessing, but unfortunately the excessive visits get me blocked by Google Scholar.
109
+
91
110
  ## Dependencies
92
111
  Dependencies (`scholarly`, `geopy`, `folium`, `tqdm`) are already taken care of when you install via pip.
93
112
 
@@ -23,8 +23,6 @@ If you open it on a browser, you will see your own version of the following cita
23
23
 
24
24
  <img src = "assets/citation_world_map.png" width=800>
25
25
 
26
- ## News
27
- `citation-map` has been upgraded to version 2.0! I finally managed to drastically speed up the process using multiprocessing (without being blocked by Google Scholar). On my personal computer, processing my profile with 100 citations took 1 hour with version 1.0 while it's now taking 5 minutes with version 2.0.
28
26
 
29
27
  ## Usage
30
28
  1. Install the package.
@@ -72,6 +70,27 @@ If you open it on a browser, you will see your own version of the following cita
72
70
  If true, print the list of citing institutions (affiliations of citing authors).
73
71
  ```
74
72
 
73
+ ## Changelog
74
+
75
+ ### Version 3.0
76
+ I realized a problem with how I used `geopy.geocoders`. A majority of the authors' self-entered affiliations are not successfully found in the system and hence are not converted to geographic coordinates on the world map. For example, the string "Yale University" is a much better entry than "Assistant Professor at Yale University".
77
+
78
+ I applied a simple fix with some rule-based language processing. This helps us identify many missing citing locations.
79
+
80
+ ### Version 2.0
81
+ I finally managed to **drastically speed up** the process using multiprocessing, in a way that avoids being blocked by Google Scholar.
82
+
83
+ On my personal computer, processing my profile with 100 citations took 1 hour with version 1.0 while it's now taking 5 minutes with version 2.0.
84
+
85
+ With that said, please be careful and do not run this tool frequently. I can easily get on Google Scholar's blacklist after a few runs.
86
+
87
+ ### Version 1.0
88
+ Very basic functionality.
89
+
90
+ This script is a bit slow. On my personal computer, it takes half a minute to process each citation. If you have thousands of citations, it may or may not be a good idea to use this script.
91
+
92
+ I tried to use multiprocessing, but unfortunately the excessive visits get me blocked by Google Scholar.
93
+
75
94
  ## Dependencies
76
95
  Dependencies (`scholarly`, `geopy`, `folium`, `tqdm`) are already taken care of when you install via pip.
77
96
 
@@ -1,6 +1,10 @@
1
+ import re
1
2
  import random
2
3
  import time
3
4
  import itertools
5
+
6
+ from typing import List
7
+ import numpy as np
4
8
  from scholarly import scholarly, ProxyGenerator
5
9
  from geopy.geocoders import Nominatim
6
10
  import folium
@@ -8,7 +12,7 @@ from tqdm import tqdm
8
12
  from multiprocessing import Pool
9
13
 
10
14
 
11
- def fetch_google_scholar_profile(scholar_id):
15
+ def fetch_google_scholar_profile(scholar_id: str):
12
16
  '''
13
17
  Step 1: Fetch Google Scholar Profile using Scholar ID.
14
18
  '''
@@ -16,11 +20,10 @@ def fetch_google_scholar_profile(scholar_id):
16
20
  author = scholarly.fill(author, sections=['publications'])
17
21
  return author
18
22
 
19
- def find_all_citing_institutions(publications, num_processes: int = 16):
23
+ def find_all_citing_institutions(publications, num_processes: int = 16) -> List[str]:
20
24
  '''
21
25
  Step 2. Final all citing institutions (i.e., insitutions of citing authors).
22
26
  '''
23
-
24
27
  # Fetch metadata for all publications, in parallel.
25
28
  with Pool(processes=num_processes) as pool:
26
29
  all_publications = list(tqdm(pool.imap(__fill_publication_metadata, publications), desc='Filling metadata for all publications...', total=len(publications)))
@@ -41,24 +44,35 @@ def find_all_citing_institutions(publications, num_processes: int = 16):
41
44
 
42
45
  return sorted(all_citing_insitutions)
43
46
 
44
- def text_to_geocode(institutions):
47
+ def clean_institution_names(institutions: List[str]) -> List[str]:
45
48
  '''
46
- Step 3: Convert institutions in plain text to Geocode.
49
+ Step 3. Clean up the name of institutions from the author's self-entered Google Scholar affiliation.
47
50
  '''
48
- geolocator = Nominatim(user_agent='citation_mapper')
49
- coordinates = []
50
- for institution in institutions:
51
- try:
52
- geo_location = geolocator.geocode(institution)
53
- if geo_location:
54
- coordinates.append((geo_location.latitude, geo_location.longitude, institution))
55
- except Exception as e:
56
- print(f'Error geocoding institution {institution}: {e}')
51
+ cleaned_institutions = []
52
+ for institution_string in institutions:
53
+ # Use a regular expression to split the string by ',', ';', or 'and'.
54
+ substring_list = [part.strip() for part in re.split(r'[;,]|\band\b', institution_string)]
55
+ for substring in substring_list:
56
+ # Use a regular expression to remove anything before 'at', or '@'.
57
+ cleaned_institution = re.sub(r'.*?\bat\b|.*?@', '', substring, flags=re.IGNORECASE).strip()
58
+ # Use a regular expression to check if the string is a common weird string.
59
+ is_common_weird_string = re.search(re.compile(r'\b(director|manager|chair|engineer|programmer|scientist|professor|lecturer|phd|student|ph\.d|department of)\b', re.IGNORECASE), substring)
60
+ if not is_common_weird_string:
61
+ cleaned_institutions.append(cleaned_institution)
62
+ return cleaned_institutions
63
+
64
+ def institution_text_to_geocode(institutions: List[str], num_processes: int = 16) -> List:
65
+ '''
66
+ Step 4: Convert institutions in plain text to Geocode.
67
+ '''
68
+ with Pool(processes=num_processes) as pool:
69
+ coordinates = list(tqdm(pool.imap(__text_to_geocode, institutions), desc='Finding all geographic coordinates...', total=len(institutions)))
70
+ coordinates = [item for item in coordinates if item is not None] # Filter out empty coordinates.
57
71
  return coordinates
58
72
 
59
73
  def create_map(coordinates, pin_colorful: bool = True):
60
74
  '''
61
- Step 4: Create the Citation World Map.
75
+ Step 5: Create the Citation World Map.
62
76
  '''
63
77
  citation_map = folium.Map(location=[20, 0], zoom_start=2)
64
78
  if pin_colorful:
@@ -100,6 +114,15 @@ def __institutions_from_authors(author_id):
100
114
  return citing_author['affiliation']
101
115
  return []
102
116
 
117
+ def __text_to_geocode(institution):
118
+ geolocator = Nominatim(user_agent='citation_mapper')
119
+ try:
120
+ geo_location = geolocator.geocode(institution)
121
+ if geo_location:
122
+ return (geo_location.latitude, geo_location.longitude, institution)
123
+ except:
124
+ return None
125
+
103
126
  def generate_citation_map(scholar_id: str,
104
127
  output_path: str = 'citation_map.html',
105
128
  num_processes: int = 16,
@@ -142,19 +165,26 @@ def generate_citation_map(scholar_id: str,
142
165
  print('\nAuthor profile found, with %d publications.\n' % len(author_profile['publications']))
143
166
 
144
167
  institutions = find_all_citing_institutions(author_profile['publications'], num_processes=num_processes)
145
- print('\nA total of %d citing institutions recorded.' % len(institutions))
168
+ print('\nA total of %d citing institutions recorded.\n' % len(institutions))
146
169
 
147
- coordinates = text_to_geocode(institutions)
170
+ if print_citing_institutions:
171
+ print('\nList of all citing institutions before cleaning:\n')
172
+ for item in np.unique(institutions):
173
+ print(item)
174
+
175
+ cleaned_institutions = clean_institution_names(institutions)
176
+
177
+ if print_citing_institutions:
178
+ print('\nList of all citing institutions after cleaning:\n')
179
+ for item in np.unique(cleaned_institutions):
180
+ print(item)
181
+
182
+ coordinates = institution_text_to_geocode(institutions + cleaned_institutions)
148
183
  print('\nConverted the institutions to Geocodes.')
149
184
 
150
185
  citation_map = create_map(coordinates, pin_colorful=pin_colorful)
151
186
  citation_map.save(output_path)
152
- print('\nMap created and saved as citation_map.html.')
153
-
154
- if print_citing_institutions:
155
- print('\nList of all citing institutions:\n')
156
- for institution in institutions:
157
- print(institution)
187
+ print('\nMap created and saved at %s.' % output_path)
158
188
  return
159
189
 
160
190
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: citation-map
3
- Version: 2.0
3
+ Version: 3.0
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
@@ -39,8 +39,6 @@ If you open it on a browser, you will see your own version of the following cita
39
39
 
40
40
  <img src = "assets/citation_world_map.png" width=800>
41
41
 
42
- ## News
43
- `citation-map` has been upgraded to version 2.0! I finally managed to drastically speed up the process using multiprocessing (without being blocked by Google Scholar). On my personal computer, processing my profile with 100 citations took 1 hour with version 1.0 while it's now taking 5 minutes with version 2.0.
44
42
 
45
43
  ## Usage
46
44
  1. Install the package.
@@ -88,6 +86,27 @@ If you open it on a browser, you will see your own version of the following cita
88
86
  If true, print the list of citing institutions (affiliations of citing authors).
89
87
  ```
90
88
 
89
+ ## Changelog
90
+
91
+ ### Version 3.0
92
+ I realized a problem with how I used `geopy.geocoders`. A majority of the authors' self-entered affiliations are not successfully found in the system and hence are not converted to geographic coordinates on the world map. For example, the string "Yale University" is a much better entry than "Assistant Professor at Yale University".
93
+
94
+ I applied a simple fix with some rule-based language processing. This helps us identify many missing citing locations.
95
+
96
+ ### Version 2.0
97
+ I finally managed to **drastically speed up** the process using multiprocessing, in a way that avoids being blocked by Google Scholar.
98
+
99
+ On my personal computer, processing my profile with 100 citations took 1 hour with version 1.0 while it's now taking 5 minutes with version 2.0.
100
+
101
+ With that said, please be careful and do not run this tool frequently. I can easily get on Google Scholar's blacklist after a few runs.
102
+
103
+ ### Version 1.0
104
+ Very basic functionality.
105
+
106
+ This script is a bit slow. On my personal computer, it takes half a minute to process each citation. If you have thousands of citations, it may or may not be a good idea to use this script.
107
+
108
+ I tried to use multiprocessing, but unfortunately the excessive visits get me blocked by Google Scholar.
109
+
91
110
  ## Dependencies
92
111
  Dependencies (`scholarly`, `geopy`, `folium`, `tqdm`) are already taken care of when you install via pip.
93
112
 
@@ -2,3 +2,4 @@ scholarly
2
2
  geopy
3
3
  folium
4
4
  tqdm
5
+ numpy
@@ -5,7 +5,7 @@ with open('README.md') as f:
5
5
 
6
6
  setup(
7
7
  name='citation-map',
8
- version='2.0',
8
+ version='3.0',
9
9
  license='MIT',
10
10
  author='Chen Liu',
11
11
  author_email='chen.liu.cl2482@yale.edu',
@@ -16,7 +16,7 @@ setup(
16
16
  long_description_content_type='text/markdown',
17
17
  url='https://github.com/ChenLiu-1996/CitationMap',
18
18
  keywords='citation map, citation world map, google scholar',
19
- install_requires=['scholarly', 'geopy', 'folium', 'tqdm'],
19
+ install_requires=['scholarly', 'geopy', 'folium', 'tqdm', 'numpy'],
20
20
  classifiers=[
21
21
  'Development Status :: 3 - Alpha', # Chose either "3 - Alpha", "4 - Beta" or "5 - Production/Stable" as the current state of your package
22
22
  'Intended Audience :: Developers', # Define that your audience are developers
File without changes
File without changes