Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit f6e7706e9f485d94295a841f0cc674f000ba9880 @mikejs mikejs committed Mar 18, 2010
Showing with 205 additions and 0 deletions.
  1. +30 −0 LICENSE
  2. +4 −0 MANIFEST
  3. +48 −0 README.rst
  4. +100 −0 duckduckgo.py
  5. +23 −0 setup.py
30 LICENSE
@@ -0,0 +1,30 @@
+BSD-style license
+=================
+
+Copyright (c) 2010, Michael Stephens
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the author nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,4 @@
+LICENSE
+README.rst
+duckduckgo.py
+setup.py
@@ -0,0 +1,48 @@
+==================
+python-duckduckgo
+==================
+
+A Python library for querying the Duck Duck Go API.
+
+Copyright Michael Stephens <me@mikej.st>, released under a BSD-style license.
+
+Source: http://github.com/mikejs/python-duckduckgo
+
+Installation
+============
+
+To install run
+
+ ``python setup.py install``
+
+Usage
+=====
+
+ >>> import duckduckgo
+ >>> r = duckduckgo.query('Duck Duck Go')
+ >>> r.type
+ 'answer'
+ >>> r.results[0].text
+ 'Official site'
+ >>> r.results[0].url
+ 'http://duckduckgo.com/'
+ >>> r.abstract.url
+ 'http://en.wikipedia.org/wiki/Duck_Duck_Go'
+ >>> r.abstract.source
+ 'Wikipedia'
+
+ >>> r = duckduckgo.query('Python')
+ >>> r.type
+ 'disambiguation'
+ >>> r.related[6].text
+ 'Python (programming language), a computer programming language'
+ >>> r.related[6].url
+ 'http://duckduckgo.com/Python_(programming_language)'
+
+ >>> r = duckduckgo.query('1 + 1')
+ >>> r.type
+ 'nothing'
+ >>> r.answer.text
+ '1 + 1 = 2'
+ >>> r.answer.type
+ 'calc'
@@ -0,0 +1,100 @@
+import urllib
+import urllib2
+from xml.etree import ElementTree
+
+__version__ = 0.1
+
+
+def query(query, useragent='python-duckduckgo 0.1'):
+ """
+ Query Duck Duck Go, returning a Results object.
+
+ Here's a query that's unlikely to change:
+
+ >>> result = query('1 + 1')
+ >>> result.type
+ 'nothing'
+ >>> result.answer.text
+ '1 + 1 = 2'
+ >>> result.answer.type
+ 'calc'
+ """
+ params = urllib.urlencode({'q': query, 'o': 'x'})
+ url = 'http://duckduckgo.com/?' + params
+
+ request = urllib2.Request(url, headers={'User-Agent': useragent})
+ response = urllib2.urlopen(request)
+ xml = ElementTree.fromstring(response.read())
+ response.close()
+
+ return Results(xml)
+
+
+class Results(object):
+
+ def __init__(self, xml):
+ self.type = {'A': 'answer', 'D': 'disambiguation',
+ 'C': 'category', 'N': 'name',
+ 'E': 'exclusive', '': 'nothing'}[xml.findtext('Type', '')]
+
+ self.api_version = xml.attrib.get('version', None)
+
+ self.heading = xml.findtext('Heading', '')
+
+ self.results = [Result(elem) for elem in xml.getiterator('Result')]
+ self.related = [Result(elem) for elem in
+ xml.getiterator('RelatedTopic')]
+
+ self.abstract = Abstract(xml)
+
+ answer_xml = xml.find('Answer')
+ if answer_xml is not None:
+ self.answer = Answer(answer_xml)
+ if not self.answer.text:
+ self.answer = None
+ else:
+ self.answer = None
+
+ image_xml = xml.find('Image')
+ if image_xml is not None and image_xml.text:
+ self.image = Image(image_xml)
+ else:
+ self.image = None
+
+
+class Abstract(object):
+
+ def __init__(self, xml):
+ self.html = xml.findtext('Abstract', '')
+ self.text = xml.findtext('AbstractText', '')
+ self.url = xml.findtext('AbstractURL', '')
+ self.source = xml.findtext('AbstractSource')
+
+
+class Result(object):
+
+ def __init__(self, xml):
+ self.html = xml.text
+ self.text = xml.findtext('Text')
+ self.url = xml.findtext('FirstURL')
+
+ icon_xml = xml.find('Icon')
+ if icon_xml is not None:
+ self.icon = Image(icon_xml)
+ else:
+ self.icon = None
+
+
+class Image(object):
+
+ def __init__(self, xml):
+ self.url = xml.text
+ self.height = xml.attrib.get('height', None)
+ self.width = xml.attrib.get('width', None)
+
+
+class Answer(object):
+
+ def __init__(self, xml):
+ self.text = xml.text
+ self.type = xml.attrib.get('type', '')
@@ -0,0 +1,23 @@
+from distutils.core import setup
+from duckduckgo import __version__
+
+long_description = open('README.rst').read()
+
+setup(name='duckduckgo',
+ version=__version__,
+ py_modules=['duckduckgo'],
+ description='Library for querying the Duck Duck Go API',
+ author='Michael Stephens',
+ author_email='me@mikej.st',
+ license='BSD',
+ url='http://github.com/mikejs/python-duckduckgo/',
+ long_description=long_description,
+ platforms=['any'],
+ classifiers=["Development Status :: 4 - Beta",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: BSD License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ "Topic :: Internet :: WWW/HTTP :: Indexing/Search",
+ ],
+ )

0 comments on commit f6e7706

Please sign in to comment.