@@ -0,0 +1,98 @@
1+#!/usr/bin/env python
2+
3+"""
4+ PubMed (Scholar publications)
5+ @website https://www.ncbi.nlm.nih.gov/pubmed/
6+ @provide-api yes (https://www.ncbi.nlm.nih.gov/home/develop/api/)
7+ @using-api yes
8+ @results XML
9+ @stable yes
10+ @parse url, title, publishedDate, content
11+ More info on api: https://www.ncbi.nlm.nih.gov/books/NBK25501/
12+"""
13+
14+from flask_babel import gettext
15+from lxml import etree
16+from datetime import datetime
17+from searx.url_utils import urlencode
18+from searx.poolrequests import get
19+
20+
21+categories = ['science']
22+
23+base_url = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi'\
24+ + '?db=pubmed&{query}&retstart={offset}&retmax={hits}'
25+
26+# engine dependent config
27+number_of_results = 10
28+pubmed_url = 'https://www.ncbi.nlm.nih.gov/pubmed/'
29+
30+
31+def request(query, params):
32+ # basic search
33+ offset = (params['pageno'] - 1) * number_of_results
34+
35+ string_args = dict(query=urlencode({'term': query}),
36+ offset=offset,
37+ hits=number_of_results)
38+
39+ params['url'] = base_url.format(**string_args)
40+
41+ return params
42+
43+
44+def response(resp):
45+ results = []
46+
47+ # First retrieve notice of each result
48+ pubmed_retrieve_api_url = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?'\
49+ + 'db=pubmed&retmode=xml&id={pmids_string}'
50+
51+ pmids_results = etree.XML(resp.content)
52+ pmids = pmids_results.xpath('//eSearchResult/IdList/Id')
53+ pmids_string = ''
54+
55+ for item in pmids:
56+ pmids_string += item.text + ','
57+
58+ retrieve_notice_args = dict(pmids_string=pmids_string)
59+
60+ retrieve_url_encoded = pubmed_retrieve_api_url.format(**retrieve_notice_args)
61+
62+ search_results_xml = get(retrieve_url_encoded).content
63+ search_results = etree.XML(search_results_xml).xpath('//PubmedArticleSet/PubmedArticle/MedlineCitation')
64+
65+ for entry in search_results:
66+ title = entry.xpath('.//Article/ArticleTitle')[0].text
67+
68+ pmid = entry.xpath('.//PMID')[0].text
69+ url = pubmed_url + pmid
70+
71+ try:
72+ content = entry.xpath('.//Abstract/AbstractText')[0].text
73+ except:
74+ content = gettext('No abstract is available for this publication.')
75+
76+ # If a doi is available, add it to the snipppet
77+ try:
78+ doi = entry.xpath('.//ELocationID[@EIdType="doi"]')[0].text
79+ content = 'DOI: {doi} Abstract: {content}'.format(doi=doi, content=content)
80+ except:
81+ pass
82+
83+ if len(content) > 300:
84+ content = content[0:300] + "..."
85+ # TODO: center snippet on query term
86+
87+ publishedDate = datetime.strptime(entry.xpath('.//DateCreated/Year')[0].text
88+ + '-' + entry.xpath('.//DateCreated/Month')[0].text
89+ + '-' + entry.xpath('.//DateCreated/Day')[0].text, '%Y-%m-%d')
90+
91+ res_dict = {'url': url,
92+ 'title': title,
93+ 'publishedDate': publishedDate,
94+ 'content': content}
95+
96+ results.append(res_dict)
97+
98+ return results