Browse Source

Merge pull request #522 from jibe-b/master

add BASE engine in category "Science"
Adam Tauber 9 years ago
parent
commit
fff9460238
3 changed files with 140 additions and 10 deletions
  1. 122
    0
      searx/engines/base.py
  2. 4
    0
      searx/settings.yml
  3. 14
    10
      searx/webapp.py

+ 122
- 0
searx/engines/base.py View File

@@ -0,0 +1,122 @@
1
+#!/usr/bin/env python
2
+
3
+"""
4
+ BASE (Scholar publications)
5
+
6
+ @website     https://base-search.net
7
+ @provide-api yes with authorization (https://api.base-search.net/)
8
+
9
+ @using-api   yes
10
+ @results     XML
11
+ @stable      ?
12
+ @parse       url, title, publishedDate, content
13
+ More info on api: http://base-search.net/about/download/base_interface.pdf
14
+"""
15
+
16
+from lxml import etree
17
+from urllib import urlencode
18
+from searx.utils import searx_useragent
19
+from cgi import escape
20
+from datetime import datetime
21
+import re
22
+
23
+
24
+categories = ['science']
25
+
26
+base_url = 'https://api.base-search.net/cgi-bin/BaseHttpSearchInterface.fcgi'\
27
+           + '?func=PerformSearch&{query}&boost=oa&hits={hits}&offset={offset}'
28
+
29
+# engine dependent config
30
+paging = True
31
+number_of_results = 10
32
+
33
+# shortcuts for advanced search
34
+shorcut_dict = {
35
+    # user-friendly keywords
36
+    'format:': 'dcformat:',
37
+    'author:': 'dccreator:',
38
+    'collection:': 'dccollection:',
39
+    'hdate:': 'dchdate:',
40
+    'contributor:': 'dccontributor:',
41
+    'coverage:': 'dccoverage:',
42
+    'date:': 'dcdate:',
43
+    'abstract:': 'dcdescription:',
44
+    'urls:': 'dcidentifier:',
45
+    'language:': 'dclanguage:',
46
+    'publisher:': 'dcpublisher:',
47
+    'relation:': 'dcrelation:',
48
+    'rights:': 'dcrights:',
49
+    'source:': 'dcsource:',
50
+    'subject:': 'dcsubject:',
51
+    'title:': 'dctitle:',
52
+    'type:': 'dcdctype:'
53
+}
54
+
55
+
56
+def request(query, params):
57
+    # replace shortcuts with API advanced search keywords
58
+    for key in shorcut_dict.keys():
59
+        query = re.sub(str(key), str(shorcut_dict[key]), query)
60
+
61
+    # basic search
62
+    offset = (params['pageno'] - 1) * number_of_results
63
+
64
+    string_args = dict(query=urlencode({'query': query}),
65
+                       offset=offset,
66
+                       hits=number_of_results)
67
+
68
+    params['url'] = base_url.format(**string_args)
69
+
70
+    params['headers']['User-Agent'] = searx_useragent()
71
+    return params
72
+
73
+
74
+def response(resp):
75
+    results = []
76
+
77
+    search_results = etree.XML(resp.content)
78
+
79
+    for entry in search_results.xpath('./result/doc'):
80
+        content = "No description available"
81
+
82
+        date = datetime.now()  # needed in case no dcdate is available for an item
83
+        for item in entry:
84
+            if item.attrib["name"] == "dchdate":
85
+                harvestDate = item.text
86
+
87
+            elif item.attrib["name"] == "dcdate":
88
+                date = item.text
89
+
90
+            elif item.attrib["name"] == "dctitle":
91
+                title = item.text
92
+
93
+            elif item.attrib["name"] == "dclink":
94
+                url = item.text
95
+
96
+            elif item.attrib["name"] == "dcdescription":
97
+                content = escape(item.text[:300])
98
+                if len(item.text) > 300:
99
+                    content += "..."
100
+
101
+# dates returned by the BASE API are not several formats
102
+        publishedDate = None
103
+        for date_format in ['%Y-%m-%dT%H:%M:%SZ', '%Y-%m-%d', '%Y-%m', '%Y']:
104
+            try:
105
+                publishedDate = datetime.strptime(date, date_format)
106
+                break
107
+            except:
108
+                pass
109
+
110
+        if publishedDate is not None:
111
+            res_dict = {'url': url,
112
+                        'title': title,
113
+                        'publishedDate': publishedDate,
114
+                        'content': content}
115
+        else:
116
+            res_dict = {'url': url,
117
+                        'title': title,
118
+                        'content': content}
119
+
120
+        results.append(res_dict)
121
+
122
+    return results

+ 4
- 0
searx/settings.yml View File

@@ -38,6 +38,10 @@ engines:
38 38
     engine : archlinux
39 39
     shortcut : al
40 40
 
41
+  - name : base
42
+    engine : base
43
+    shortcut : bs
44
+
41 45
   - name : wikipedia
42 46
     engine : mediawiki
43 47
     shortcut : wp

+ 14
- 10
searx/webapp.py View File

@@ -408,17 +408,21 @@ def index():
408 408
 
409 409
         # TODO, check if timezone is calculated right
410 410
         if 'publishedDate' in result:
411
-            result['pubdate'] = result['publishedDate'].strftime('%Y-%m-%d %H:%M:%S%z')
412
-            if result['publishedDate'].replace(tzinfo=None) >= datetime.now() - timedelta(days=1):
413
-                timedifference = datetime.now() - result['publishedDate'].replace(tzinfo=None)
414
-                minutes = int((timedifference.seconds / 60) % 60)
415
-                hours = int(timedifference.seconds / 60 / 60)
416
-                if hours == 0:
417
-                    result['publishedDate'] = gettext(u'{minutes} minute(s) ago').format(minutes=minutes)
418
-                else:
419
-                    result['publishedDate'] = gettext(u'{hours} hour(s), {minutes} minute(s) ago').format(hours=hours, minutes=minutes)  # noqa
411
+            try:  # test if publishedDate >= 1900 (datetime module bug)
412
+                result['pubdate'] = result['publishedDate'].strftime('%Y-%m-%d %H:%M:%S%z')
413
+            except ValueError:
414
+                result['publishedDate'] = None
420 415
             else:
421
-                result['publishedDate'] = format_date(result['publishedDate'])
416
+                if result['publishedDate'].replace(tzinfo=None) >= datetime.now() - timedelta(days=1):
417
+                    timedifference = datetime.now() - result['publishedDate'].replace(tzinfo=None)
418
+                    minutes = int((timedifference.seconds / 60) % 60)
419
+                    hours = int(timedifference.seconds / 60 / 60)
420
+                    if hours == 0:
421
+                        result['publishedDate'] = gettext(u'{minutes} minute(s) ago').format(minutes=minutes)
422
+                    else:
423
+                        result['publishedDate'] = gettext(u'{hours} hour(s), {minutes} minute(s) ago').format(hours=hours, minutes=minutes)  # noqa
424
+                else:
425
+                    result['publishedDate'] = format_date(result['publishedDate'])
422 426
 
423 427
     if search.request_data.get('format') == 'json':
424 428
         return Response(json.dumps({'query': search.query,