Source code for AuDoLab.subclasses.abstractscraper_pubmed
import warnings
from bs4 import BeautifulSoup
import requests
import pandas as pd
import unicodedata
from tqdm import tqdm
[docs]def warn(*args, **kwargs):
pass
warnings.warn = warn
[docs]class AbstractScraper_Pubmed:
def __init__(self):
pass
def _find_links(self, url, number_of_pages):
"""finds paper links associated with given url search query
Args:
url (str): Link from arxiv.org with search query
number_of_pages (int): number of pages that should be scraped.
"""
html = requests.get(url).text
# get urls of pages staring from 1
self.pages = [url + "&page=" + str(i) for i in range(1, number_of_pages + 1)]
self.pages = list(set(self.pages))
self.document_links = []
# print statement so everybody knows what is happening
if len(self.pages) == 1:
print("The algorithm is iterating through", len(self.pages), "page")
else:
print("The algorithm is iterating through", len(self.pages), "pages")
# loop through all pages and extract links
for i in tqdm(range(len(self.pages))):
html = requests.get(self.pages[i]).text
for link in BeautifulSoup(html, features="html.parser").findAll(
"a", {"class": "docsum-title"}
):
self.document_links.append(
"https://pubmed.ncbi.nlm.nih.gov" + link["href"]
)
print(
"The algorithm found ",
len(self.document_links),
" unique abstracts to in your query. \n Try increasing the number of pages if you want to scrape more papers",
)
def _scrape(self, author=True):
"""loop through all found paper links and scrape abstracts, titles and
authors.
Args:
author (bool, optional): if true all author names are scraped as well. Defaults to True.
"""
# initiliaze empty lists
self.abstracts = []
self.titles = []
self.authors = []
# loop through links and extract abstracts, titles and authors
for url in tqdm(self.document_links):
# for every link get underlying html code
html = requests.get(url).text
soup = BeautifulSoup(html, "html.parser")
# use try (without specifiyng exception) for adapting to changes in
# source data
# extract all abstracts with beautifulSoup
try:
abstract = soup.find("div", class_="abstract-content selected")
# extract the text between <span>
abstract = abstract.text.replace("\n", "")
# append to data
self.abstracts.append(abstract)
except BaseException:
self.abstracts.append(None)
try:
title = soup.find("h1", class_="heading-title")
title = title.text.replace("\n", "")
self.titles.append(title)
except BaseException:
self.titles.append(None)
if author == True:
try:
authors = soup.find("div", class_="authors")
authors = authors.text.replace("\n", "")
authors = unicodedata.normalize("NFKD", authors)
authors = authors.replace(" ", "")
authors = "".join(i for i in authors if not i.isdigit())
self.authors.append(authors)
except BaseException:
self.authors.append(None)
data = pd.DataFrame(
{
"abstract": self.abstracts,
"title": self.titles,
"authors": self.authors,
}
)
else:
data = pd.DataFrame(
{
"abstract": self.abstracts,
"title": self.titles,
}
)
self.data = data.drop_duplicates()
[docs] def scrape_pubmed(self, url, pages=8, author=True):
"""Scrapes https://pubmed.ncbi and returns a pd.DataFrame containing
abstracts, titles and author names.
Returns these informations based on the users given url (search query),
e.g. url="https://pubmed.ncbi.nlm.nih.gov/?term=medicine"
Args:
url (string): link of searchquery from arxiv.org
pages (int, optional): number of pages the algorithm iterates through and searches for abstracts. Defaults to 8.
author (bool, optional): if true all author names are scraped as well. Defaults to True.
Returns:
pd.DataFrame: DataFrame that contains: Abstracts, Titles and Authors
"""
if "pubmed" not in url:
return print(
"ERROR: Only specify a url/search query via https://pubmed.ncbi"
)
else:
self._find_links(url=url, number_of_pages=pages)
self._scrape(author)
return self.data
if __name__ == "__main__":
AS = AbstractScraper_Pubmed()
test = AS.scrape_pubmed("https://pubmed.ncbi.nlm.nih.gov/?term=medicine", 3, False)