citation-map 4.3__tar.gz → 4.4__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-4.3 → citation-map-4.4}/PKG-INFO +13 -1
- {citation-map-4.3 → citation-map-4.4}/README.md +12 -0
- {citation-map-4.3 → citation-map-4.4}/citation_map/citation_map.py +117 -77
- {citation-map-4.3 → citation-map-4.4}/citation_map/scholarly_support.py +1 -1
- {citation-map-4.3 → citation-map-4.4}/citation_map.egg-info/PKG-INFO +13 -1
- {citation-map-4.3 → citation-map-4.4}/setup.py +1 -1
- {citation-map-4.3 → citation-map-4.4}/LICENSE.md +0 -0
- {citation-map-4.3 → citation-map-4.4}/citation_map/__init__.py +0 -0
- {citation-map-4.3 → citation-map-4.4}/citation_map.egg-info/SOURCES.txt +0 -0
- {citation-map-4.3 → citation-map-4.4}/citation_map.egg-info/dependency_links.txt +0 -0
- {citation-map-4.3 → citation-map-4.4}/citation_map.egg-info/requires.txt +0 -0
- {citation-map-4.3 → citation-map-4.4}/citation_map.egg-info/top_level.txt +0 -0
- {citation-map-4.3 → citation-map-4.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: citation-map
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.4
|
|
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
|
|
@@ -115,6 +115,8 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
|
|
|
115
115
|
generate_citation_map(scholar_id)
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
+
Note that in Version 4.4, we support manual edit of the csv. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
|
|
119
|
+
|
|
118
120
|
Note that in Version 4.0, we will cache the results before identifying affiliations. So if you want to rerun the same author from scratch, you need to delete the cache (default location is 'cache').
|
|
119
121
|
|
|
120
122
|
More input arguments are shown in [the demo script](https://github.com/ChenLiu-1996/CitationMap/blob/main/demo/demo.py).
|
|
@@ -203,6 +205,16 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
|
|
|
203
205
|
```
|
|
204
206
|
|
|
205
207
|
## Changelog
|
|
208
|
+
<details>
|
|
209
|
+
<summary>Version 4.4 (Dec 6, 2024)</summary>
|
|
210
|
+
<br>
|
|
211
|
+
|
|
212
|
+
1. **Support manual edit of the csv.** Note you do need to manually correct the coordinates too if you choose to use this functionality. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
|
|
213
|
+
2. Slight optimization on caching.
|
|
214
|
+
|
|
215
|
+
</details>
|
|
216
|
+
|
|
217
|
+
|
|
206
218
|
<details>
|
|
207
219
|
<summary>Version 4.0 (Aug 2, 2024)</summary>
|
|
208
220
|
<br>
|
|
@@ -99,6 +99,8 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
|
|
|
99
99
|
generate_citation_map(scholar_id)
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
+
Note that in Version 4.4, we support manual edit of the csv. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
|
|
103
|
+
|
|
102
104
|
Note that in Version 4.0, we will cache the results before identifying affiliations. So if you want to rerun the same author from scratch, you need to delete the cache (default location is 'cache').
|
|
103
105
|
|
|
104
106
|
More input arguments are shown in [the demo script](https://github.com/ChenLiu-1996/CitationMap/blob/main/demo/demo.py).
|
|
@@ -187,6 +189,16 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
|
|
|
187
189
|
```
|
|
188
190
|
|
|
189
191
|
## Changelog
|
|
192
|
+
<details>
|
|
193
|
+
<summary>Version 4.4 (Dec 6, 2024)</summary>
|
|
194
|
+
<br>
|
|
195
|
+
|
|
196
|
+
1. **Support manual edit of the csv.** Note you do need to manually correct the coordinates too if you choose to use this functionality. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
|
|
197
|
+
2. Slight optimization on caching.
|
|
198
|
+
|
|
199
|
+
</details>
|
|
200
|
+
|
|
201
|
+
|
|
190
202
|
<details>
|
|
191
203
|
<summary>Version 4.0 (Aug 2, 2024)</summary>
|
|
192
204
|
<br>
|
|
@@ -14,7 +14,7 @@ from geopy.geocoders import Nominatim
|
|
|
14
14
|
from multiprocessing import Pool
|
|
15
15
|
from scholarly import scholarly, ProxyGenerator
|
|
16
16
|
from tqdm import tqdm
|
|
17
|
-
from typing import Any,
|
|
17
|
+
from typing import Any, List, Tuple
|
|
18
18
|
|
|
19
19
|
from .scholarly_support import get_citing_author_ids_and_citing_papers, get_organization_name
|
|
20
20
|
|
|
@@ -178,9 +178,32 @@ def affiliation_text_to_geocode(author_paper_affiliation_tuple_list: List[Tuple[
|
|
|
178
178
|
coordinates_and_info = [item for item in coordinates_and_info if item is not None] # Filter out empty entries.
|
|
179
179
|
return coordinates_and_info
|
|
180
180
|
|
|
181
|
+
def export_dict_to_csv(coordinates_and_info: List[Tuple[str]], csv_output_path: str) -> None:
|
|
182
|
+
'''
|
|
183
|
+
Step 5.1: Export csv file recording citation information.
|
|
184
|
+
'''
|
|
185
|
+
|
|
186
|
+
citation_df = pd.DataFrame(coordinates_and_info,
|
|
187
|
+
columns=['citing author name', 'citing paper title', 'cited paper title',
|
|
188
|
+
'affiliation', 'latitude', 'longitude',
|
|
189
|
+
'county', 'city', 'state', 'country'])
|
|
190
|
+
|
|
191
|
+
citation_df.to_csv(csv_output_path)
|
|
192
|
+
return
|
|
193
|
+
|
|
194
|
+
def read_csv_to_dict(csv_path: str) -> None:
|
|
195
|
+
'''
|
|
196
|
+
Step 5.1: Read csv file recording citation information.
|
|
197
|
+
Only relevant if `read_from_csv` is True.
|
|
198
|
+
'''
|
|
199
|
+
|
|
200
|
+
citation_df = pd.read_csv(csv_path, index_col=0)
|
|
201
|
+
coordinates_and_info = list(citation_df.itertuples(index=False, name=None))
|
|
202
|
+
return coordinates_and_info
|
|
203
|
+
|
|
181
204
|
def create_map(coordinates_and_info: List[Tuple[str]], pin_colorful: bool = True):
|
|
182
205
|
'''
|
|
183
|
-
Step 5.
|
|
206
|
+
Step 5.2: Create the Citation World Map.
|
|
184
207
|
|
|
185
208
|
For authors under the same affiliations, they will be displayed in the same pin.
|
|
186
209
|
'''
|
|
@@ -218,18 +241,6 @@ def create_map(coordinates_and_info: List[Tuple[str]], pin_colorful: bool = True
|
|
|
218
241
|
folium.Marker([lat, lon], popup='%s (%s)' % (affiliation_name, ' & '.join(author_name_list))).add_to(citation_map)
|
|
219
242
|
return citation_map
|
|
220
243
|
|
|
221
|
-
def export_csv(coordinates_and_info: List[Tuple[str]], csv_output_path: str) -> None:
|
|
222
|
-
'''
|
|
223
|
-
Step 5.2: Export csv file recording citation information.
|
|
224
|
-
'''
|
|
225
|
-
|
|
226
|
-
citation_df = pd.DataFrame(coordinates_and_info,
|
|
227
|
-
columns=['citing author name', 'citing paper title', 'cited paper title',
|
|
228
|
-
'affiliation', 'latitude', 'longitude',
|
|
229
|
-
'county', 'city', 'state', 'country'])
|
|
230
|
-
|
|
231
|
-
citation_df.to_csv(csv_output_path)
|
|
232
|
-
return
|
|
233
244
|
|
|
234
245
|
def __fill_publication_metadata(pub):
|
|
235
246
|
time.sleep(random.uniform(1, 5)) # Random delay to reduce risk of being blocked.
|
|
@@ -329,6 +340,7 @@ def load_cache(fpath: str) -> Any:
|
|
|
329
340
|
def generate_citation_map(scholar_id: str,
|
|
330
341
|
output_path: str = 'citation_map.html',
|
|
331
342
|
csv_output_path: str = 'citation_info.csv',
|
|
343
|
+
parse_csv: bool = False,
|
|
332
344
|
cache_folder: str = 'cache',
|
|
333
345
|
affiliation_conservative: bool = False,
|
|
334
346
|
num_processes: int = 16,
|
|
@@ -348,6 +360,9 @@ def generate_citation_map(scholar_id: str,
|
|
|
348
360
|
csv_output_path: str
|
|
349
361
|
(default is 'citation_info.csv')
|
|
350
362
|
The path to the output csv file.
|
|
363
|
+
parse_csv: bool
|
|
364
|
+
(default is False)
|
|
365
|
+
If True, will directly jump to Step 5.2, using the information loaded from the csv.
|
|
351
366
|
cache_folder: str
|
|
352
367
|
(default is 'cache')
|
|
353
368
|
The folder to save intermediate results, after finding (author, paper) but before finding the affiliations.
|
|
@@ -373,85 +388,110 @@ def generate_citation_map(scholar_id: str,
|
|
|
373
388
|
If true, print the list of citing affiliations (affiliations of citing authors).
|
|
374
389
|
'''
|
|
375
390
|
|
|
376
|
-
if
|
|
377
|
-
pg = ProxyGenerator()
|
|
378
|
-
pg.FreeProxies()
|
|
379
|
-
scholarly.use_proxy(pg)
|
|
380
|
-
print('Using proxy.')
|
|
391
|
+
if not parse_csv:
|
|
381
392
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
393
|
+
if use_proxy:
|
|
394
|
+
pg = ProxyGenerator()
|
|
395
|
+
pg.FreeProxies()
|
|
396
|
+
scholarly.use_proxy(pg)
|
|
397
|
+
print('Using proxy.')
|
|
386
398
|
|
|
387
|
-
|
|
388
|
-
|
|
399
|
+
if cache_folder is not None:
|
|
400
|
+
cache_path = os.path.join(cache_folder, scholar_id, 'all_citing_author_paper_tuple_list.pkl')
|
|
401
|
+
else:
|
|
402
|
+
cache_path = None
|
|
389
403
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
all_citing_author_paper_tuple_list = find_all_citing_authors(scholar_id=scholar_id,
|
|
393
|
-
num_processes=num_processes)
|
|
394
|
-
print('A total of %d citing authors recorded.\n' % len(all_citing_author_paper_tuple_list))
|
|
395
|
-
if cache_path is not None and len(all_citing_author_paper_tuple_list) > 0:
|
|
396
|
-
save_cache(all_citing_author_paper_tuple_list, cache_path)
|
|
397
|
-
print('Saved to cache: %s.\n' % cache_path)
|
|
404
|
+
if cache_path is None or not os.path.exists(cache_path):
|
|
405
|
+
print('No cache found for this author. Finding citing authors from scratch.\n')
|
|
398
406
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
407
|
+
# NOTE: Step 1. Find all publications of the given Google Scholar ID.
|
|
408
|
+
# Step 2. Find all citing authors.
|
|
409
|
+
all_citing_author_paper_tuple_list = find_all_citing_authors(scholar_id=scholar_id,
|
|
410
|
+
num_processes=num_processes)
|
|
411
|
+
print('A total of %d citing authors recorded.\n' % len(all_citing_author_paper_tuple_list))
|
|
412
|
+
if cache_path is not None and len(all_citing_author_paper_tuple_list) > 0:
|
|
413
|
+
save_cache(all_citing_author_paper_tuple_list, cache_path)
|
|
414
|
+
print('Saved to cache: %s.\n' % cache_path)
|
|
415
|
+
|
|
416
|
+
else:
|
|
417
|
+
print('Cache found. Loading author paper information from cache.\n')
|
|
418
|
+
all_citing_author_paper_tuple_list = load_cache(cache_path)
|
|
419
|
+
print('Loaded from cache: %s.\n' % cache_path)
|
|
420
|
+
print('A total of %d citing authors loaded.\n' % len(all_citing_author_paper_tuple_list))
|
|
421
|
+
|
|
422
|
+
if cache_folder is not None:
|
|
423
|
+
cache_path = os.path.join(cache_folder, scholar_id, 'author_paper_affiliation_tuple_list.pkl')
|
|
424
|
+
else:
|
|
425
|
+
cache_path = None
|
|
426
|
+
|
|
427
|
+
if cache_path is None or not os.path.exists(cache_path):
|
|
428
|
+
print('No cache found for this author. Finding citing affiliations from scratch.\n')
|
|
429
|
+
|
|
430
|
+
# NOTE: Step 2. Find all citing affiliations.
|
|
431
|
+
print('Identifying affiliations using the %s approach.' % ('conservative' if affiliation_conservative else 'aggressive'))
|
|
432
|
+
author_paper_affiliation_tuple_list = find_all_citing_affiliations(all_citing_author_paper_tuple_list,
|
|
433
|
+
num_processes=num_processes,
|
|
434
|
+
affiliation_conservative=affiliation_conservative)
|
|
435
|
+
print('\nA total of %d citing affiliations recorded.\n' % len(author_paper_affiliation_tuple_list))
|
|
436
|
+
# Take unique tuples.
|
|
437
|
+
author_paper_affiliation_tuple_list = list(set(author_paper_affiliation_tuple_list))
|
|
438
|
+
|
|
439
|
+
# NOTE: Step 3. Clean the affiliation strings (optional, only used if taking the aggressive approach).
|
|
440
|
+
if print_citing_affiliations:
|
|
441
|
+
if affiliation_conservative:
|
|
442
|
+
print('Taking the conservative approach. Will not need to clean the affiliation names.')
|
|
443
|
+
print('List of all citing authors and affiliations:\n')
|
|
444
|
+
else:
|
|
445
|
+
print('Taking the aggressive approach. Cleaning the affiliation names.')
|
|
446
|
+
print('List of all citing authors and affiliations before cleaning:\n')
|
|
447
|
+
__print_author_and_affiliation(author_paper_affiliation_tuple_list)
|
|
448
|
+
if not affiliation_conservative:
|
|
449
|
+
cleaned_author_paper_affiliation_tuple_list = clean_affiliation_names(author_paper_affiliation_tuple_list)
|
|
450
|
+
if print_citing_affiliations:
|
|
451
|
+
print('List of all citing authors and affiliations after cleaning:\n')
|
|
452
|
+
__print_author_and_affiliation(cleaned_author_paper_affiliation_tuple_list)
|
|
453
|
+
# Use the merged set to maximize coverage.
|
|
454
|
+
author_paper_affiliation_tuple_list += cleaned_author_paper_affiliation_tuple_list
|
|
455
|
+
# Take unique tuples.
|
|
456
|
+
author_paper_affiliation_tuple_list = list(set(author_paper_affiliation_tuple_list))
|
|
457
|
+
|
|
458
|
+
if cache_path is not None and len(author_paper_affiliation_tuple_list) > 0:
|
|
459
|
+
save_cache(author_paper_affiliation_tuple_list, cache_path)
|
|
460
|
+
print('Saved to cache: %s.\n' % cache_path)
|
|
416
461
|
|
|
417
|
-
# NOTE: Step 3. Clean the affiliation strings (optional, only used if taking the aggressive approach).
|
|
418
|
-
if print_citing_affiliations:
|
|
419
|
-
if affiliation_conservative:
|
|
420
|
-
print('Taking the conservative approach. Will not need to clean the affiliation names.')
|
|
421
|
-
print('List of all citing authors and affiliations:\n')
|
|
422
462
|
else:
|
|
423
|
-
print('
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
__print_author_and_affiliation(cleaned_author_paper_affiliation_tuple_list)
|
|
431
|
-
# Use the merged set to maximize coverage.
|
|
432
|
-
author_paper_affiliation_tuple_list += cleaned_author_paper_affiliation_tuple_list
|
|
463
|
+
print('Cache found. Loading author paper and affiliation information from cache.\n')
|
|
464
|
+
author_paper_affiliation_tuple_list = load_cache(cache_path)
|
|
465
|
+
print('List of all citing authors and affiliations loaded:\n')
|
|
466
|
+
__print_author_and_affiliation(author_paper_affiliation_tuple_list)
|
|
467
|
+
|
|
468
|
+
# NOTE: Step 4. Convert affiliations in plain text to Geocode.
|
|
469
|
+
coordinates_and_info = affiliation_text_to_geocode(author_paper_affiliation_tuple_list)
|
|
433
470
|
# Take unique tuples.
|
|
434
|
-
|
|
471
|
+
coordinates_and_info = list(set(coordinates_and_info))
|
|
435
472
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
coordinates_and_info = list(set(coordinates_and_info))
|
|
473
|
+
# NOTE: Step 5.1. Export csv file recording citation information.
|
|
474
|
+
export_dict_to_csv(coordinates_and_info, csv_output_path)
|
|
475
|
+
print('\nCitation information exported to %s.' % csv_output_path)
|
|
440
476
|
|
|
441
|
-
|
|
477
|
+
else:
|
|
478
|
+
print('\nDirectly parsing the csv. Skipping all previous steps.')
|
|
479
|
+
assert os.path.isfile(csv_output_path), '`csv_output_path` is not a file.'
|
|
480
|
+
coordinates_and_info = read_csv_to_dict(csv_output_path)
|
|
481
|
+
print('\nCitation information loaded from %s.' % csv_output_path)
|
|
482
|
+
|
|
483
|
+
# NOTE: Step 5.2. Create the citation world map.
|
|
442
484
|
citation_map = create_map(coordinates_and_info, pin_colorful=pin_colorful)
|
|
443
485
|
citation_map.save(output_path)
|
|
444
|
-
print('\
|
|
445
|
-
|
|
446
|
-
# NOTE: Step 5.2. Export csv file recording citation information.
|
|
447
|
-
export_csv(coordinates_and_info, csv_output_path)
|
|
448
|
-
print('\nCitation information exported to %s.' % csv_output_path)
|
|
486
|
+
print('\nHTML map created and saved at %s.\n' % output_path)
|
|
449
487
|
return
|
|
450
488
|
|
|
451
489
|
|
|
452
490
|
if __name__ == '__main__':
|
|
453
491
|
# Replace this with your Google Scholar ID.
|
|
454
492
|
scholar_id = '3rDjnykAAAAJ'
|
|
455
|
-
generate_citation_map(scholar_id, output_path='citation_map.html',
|
|
493
|
+
generate_citation_map(scholar_id, output_path='citation_map.html',
|
|
494
|
+
csv_output_path='citation_info.csv',
|
|
495
|
+
parse_csv=False,
|
|
456
496
|
cache_folder='cache', affiliation_conservative=True, num_processes=16,
|
|
457
497
|
use_proxy=False, pin_colorful=True, print_citing_affiliations=True)
|
|
@@ -30,7 +30,7 @@ def get_html_per_citation_page(soup) -> List[str]:
|
|
|
30
30
|
citing_authors_and_citing_papers.append((author_id, title))
|
|
31
31
|
paper_parsed = True
|
|
32
32
|
if not paper_parsed:
|
|
33
|
-
print("[WARNING!] Could not find author links for ",
|
|
33
|
+
print("[WARNING!] Could not find author links for ", title)
|
|
34
34
|
else:
|
|
35
35
|
continue
|
|
36
36
|
return citing_authors_and_citing_papers
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: citation-map
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.4
|
|
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
|
|
@@ -115,6 +115,8 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
|
|
|
115
115
|
generate_citation_map(scholar_id)
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
+
Note that in Version 4.4, we support manual edit of the csv. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
|
|
119
|
+
|
|
118
120
|
Note that in Version 4.0, we will cache the results before identifying affiliations. So if you want to rerun the same author from scratch, you need to delete the cache (default location is 'cache').
|
|
119
121
|
|
|
120
122
|
More input arguments are shown in [the demo script](https://github.com/ChenLiu-1996/CitationMap/blob/main/demo/demo.py).
|
|
@@ -203,6 +205,16 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
|
|
|
203
205
|
```
|
|
204
206
|
|
|
205
207
|
## Changelog
|
|
208
|
+
<details>
|
|
209
|
+
<summary>Version 4.4 (Dec 6, 2024)</summary>
|
|
210
|
+
<br>
|
|
211
|
+
|
|
212
|
+
1. **Support manual edit of the csv.** Note you do need to manually correct the coordinates too if you choose to use this functionality. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
|
|
213
|
+
2. Slight optimization on caching.
|
|
214
|
+
|
|
215
|
+
</details>
|
|
216
|
+
|
|
217
|
+
|
|
206
218
|
<details>
|
|
207
219
|
<summary>Version 4.0 (Aug 2, 2024)</summary>
|
|
208
220
|
<br>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|