From 47090717377600b829e9844d350eff2196717c40 Mon Sep 17 00:00:00 2001 From: Bobby Larson Date: Fri, 20 Jun 2014 09:31:42 -0600 Subject: [PATCH 1/2] Ran autopep8 on all python scripts. --- alchemyapi.py | 1459 ++++++++++++++++++++++++------------------------- example.py | 474 ++++++++-------- tests.py | 223 ++++---- 3 files changed, 1059 insertions(+), 1097 deletions(-) diff --git a/alchemyapi.py b/alchemyapi.py index 5e91215..d0c81df 100644 --- a/alchemyapi.py +++ b/alchemyapi.py @@ -19,753 +19,730 @@ import requests try: - from urllib.request import urlopen - from urllib.parse import urlparse - from urllib.parse import urlencode -except ImportError: - from urlparse import urlparse - from urllib2 import urlopen - from urllib import urlencode + from urllib.request import urlopen + from urllib.parse import urlparse + from urllib.parse import urlencode +except ImportError: + from urlparse import urlparse + from urllib2 import urlopen + from urllib import urlencode try: - import json + import json except ImportError: - #Older versions of Python (i.e. 2.4) require simplejson instead of json - import simplejson as json + # Older versions of Python (i.e. 2.4) require simplejson instead of json + import simplejson as json if __name__ == '__main__': - """ - Writes the API key to api_key.txt file. It will create the file if it doesn't exist. - This function is intended to be called from the Python command line using: python alchemyapi YOUR_API_KEY - If you don't have an API key yet, register for one at: http://www.alchemyapi.com/api/register.html - - INPUT: - argv[1] -> Your API key from AlchemyAPI. Should be 40 hex characters - - OUTPUT: - none - """ - - import sys - if len(sys.argv) == 2 and sys.argv[1]: - if len(sys.argv[1]) == 40: - #write the key to the file - f = open('api_key.txt','w') - f.write(sys.argv[1]) - f.close() - print('Key: ' + sys.argv[1] + ' was written to api_key.txt') - print('You are now ready to start using AlchemyAPI. For an example, run: python example.py') - else: - print('The key appears to invalid. Please make sure to use the 40 character key assigned by AlchemyAPI') - + """ + Writes the API key to api_key.txt file. It will create the file if it doesn't exist. + This function is intended to be called from the Python command line using: python alchemyapi YOUR_API_KEY + If you don't have an API key yet, register for one at: http://www.alchemyapi.com/api/register.html + + INPUT: + argv[1] -> Your API key from AlchemyAPI. Should be 40 hex characters + + OUTPUT: + none + """ + + import sys + if len(sys.argv) == 2 and sys.argv[1]: + if len(sys.argv[1]) == 40: + # write the key to the file + f = open('api_key.txt', 'w') + f.write(sys.argv[1]) + f.close() + print('Key: ' + sys.argv[1] + ' was written to api_key.txt') + print( + 'You are now ready to start using AlchemyAPI. For an example, run: python example.py') + else: + print( + 'The key appears to invalid. Please make sure to use the 40 character key assigned by AlchemyAPI') class AlchemyAPI: - #Setup the endpoints - ENDPOINTS = {} - ENDPOINTS['sentiment'] = {} - ENDPOINTS['sentiment']['url'] = '/url/URLGetTextSentiment' - ENDPOINTS['sentiment']['text'] = '/text/TextGetTextSentiment' - ENDPOINTS['sentiment']['html'] = '/html/HTMLGetTextSentiment' - ENDPOINTS['sentiment_targeted'] = {} - ENDPOINTS['sentiment_targeted']['url'] = '/url/URLGetTargetedSentiment' - ENDPOINTS['sentiment_targeted']['text'] = '/text/TextGetTargetedSentiment' - ENDPOINTS['sentiment_targeted']['html'] = '/html/HTMLGetTargetedSentiment' - ENDPOINTS['author'] = {} - ENDPOINTS['author']['url'] = '/url/URLGetAuthor' - ENDPOINTS['author']['html'] = '/html/HTMLGetAuthor' - ENDPOINTS['keywords'] = {} - ENDPOINTS['keywords']['url'] = '/url/URLGetRankedKeywords' - ENDPOINTS['keywords']['text'] = '/text/TextGetRankedKeywords' - ENDPOINTS['keywords']['html'] = '/html/HTMLGetRankedKeywords' - ENDPOINTS['concepts'] = {} - ENDPOINTS['concepts']['url'] = '/url/URLGetRankedConcepts' - ENDPOINTS['concepts']['text'] = '/text/TextGetRankedConcepts' - ENDPOINTS['concepts']['html'] = '/html/HTMLGetRankedConcepts' - ENDPOINTS['entities'] = {} - ENDPOINTS['entities']['url'] = '/url/URLGetRankedNamedEntities' - ENDPOINTS['entities']['text'] = '/text/TextGetRankedNamedEntities' - ENDPOINTS['entities']['html'] = '/html/HTMLGetRankedNamedEntities' - ENDPOINTS['category'] = {} - ENDPOINTS['category']['url'] = '/url/URLGetCategory' - ENDPOINTS['category']['text'] = '/text/TextGetCategory' - ENDPOINTS['category']['html'] = '/html/HTMLGetCategory' - ENDPOINTS['relations'] = {} - ENDPOINTS['relations']['url'] = '/url/URLGetRelations' - ENDPOINTS['relations']['text'] = '/text/TextGetRelations' - ENDPOINTS['relations']['html'] = '/html/HTMLGetRelations' - ENDPOINTS['language'] = {} - ENDPOINTS['language']['url'] = '/url/URLGetLanguage' - ENDPOINTS['language']['text'] = '/text/TextGetLanguage' - ENDPOINTS['language']['html'] = '/html/HTMLGetLanguage' - ENDPOINTS['text'] = {} - ENDPOINTS['text']['url'] = '/url/URLGetText' - ENDPOINTS['text']['html'] = '/html/HTMLGetText' - ENDPOINTS['text_raw'] = {} - ENDPOINTS['text_raw']['url'] = '/url/URLGetRawText' - ENDPOINTS['text_raw']['html'] = '/html/HTMLGetRawText' - ENDPOINTS['title'] = {} - ENDPOINTS['title']['url'] = '/url/URLGetTitle' - ENDPOINTS['title']['html'] = '/html/HTMLGetTitle' - ENDPOINTS['feeds'] = {} - ENDPOINTS['feeds']['url'] = '/url/URLGetFeedLinks' - ENDPOINTS['feeds']['html'] = '/html/HTMLGetFeedLinks' - ENDPOINTS['microformats'] = {} - ENDPOINTS['microformats']['url'] = '/url/URLGetMicroformatData' - ENDPOINTS['microformats']['html'] = '/html/HTMLGetMicroformatData' - ENDPOINTS['combined'] = {} - ENDPOINTS['combined']['url'] = '/url/URLGetCombinedData' - ENDPOINTS['combined']['text'] = '/text/TextGetCombinedData' - ENDPOINTS['image'] = {} - ENDPOINTS['image']['url'] = '/url/URLGetImage' - ENDPOINTS['imagetagging'] = {} - ENDPOINTS['imagetagging']['url'] = '/url/URLGetRankedImageKeywords' - ENDPOINTS['imagetagging']['image'] = '/image/ImageGetRankedImageKeywords' - ENDPOINTS['taxonomy'] = {} - ENDPOINTS['taxonomy']['url'] = '/url/URLGetRankedTaxonomy' - ENDPOINTS['taxonomy']['html'] = '/html/HTMLGetRankedTaxonomy' - ENDPOINTS['taxonomy']['text'] = '/text/TextGetRankedTaxonomy' - - #The base URL for all endpoints - BASE_URL = 'http://access.alchemyapi.com/calls' - - s = requests.Session() - - def __init__(self): - """ - Initializes the SDK so it can send requests to AlchemyAPI for analysis. - It loads the API key from api_key.txt and configures the endpoints. - """ - - import sys - try: - # Open the key file and read the key - f = open("api_key.txt", "r") - key = f.read().strip() - - if key == '': - #The key file should't be blank - print('The api_key.txt file appears to be blank, please run: python alchemyapi.py YOUR_KEY_HERE') - print('If you do not have an API Key from AlchemyAPI, please register for one at: http://www.alchemyapi.com/api/register.html') - sys.exit(0) - elif len(key) != 40: - #Keys should be exactly 40 characters long - print('It appears that the key in api_key.txt is invalid. Please make sure the file only includes the API key, and it is the correct one.') - sys.exit(0) - else: - #setup the key - self.apikey = key - - # Close file - f.close() - except IOError: - #The file doesn't exist, so show the message and create the file. - print('API Key not found! Please run: python alchemyapi.py YOUR_KEY_HERE') - print('If you do not have an API Key from AlchemyAPI, please register for one at: http://www.alchemyapi.com/api/register.html') - - #create a blank key file - open('api_key.txt', 'a').close() - sys.exit(0) - except Exception as e: - print(e) - - - - def entities(self, flavor, data, options={}): - """ - Extracts the entities for text, a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/entity-extraction/ - For the docs, please refer to: http://www.alchemyapi.com/api/entity-extraction/ - - INPUT: - flavor -> which version of the call, i.e. text, url or html. - data -> the data to analyze, either the text, the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - disambiguate -> disambiguate entities (i.e. Apple the company vs. apple the fruit). 0: disabled, 1: enabled (default) - linkedData -> include linked data on disambiguated entities. 0: disabled, 1: enabled (default) - coreference -> resolve coreferences (i.e. the pronouns that correspond to named entities). 0: disabled, 1: enabled (default) - quotations -> extract quotations by entities. 0: disabled (default), 1: enabled. - sentiment -> analyze sentiment for each entity. 0: disabled (default), 1: enabled. Requires 1 additional API transction if enabled. - showSourceText -> 0: disabled (default), 1: enabled - maxRetrieve -> the maximum number of entities to retrieve (default: 50) - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['entities']: - return { 'status':'ERROR', 'statusInfo':'entity extraction for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['entities'][flavor], {}, options) - - - - def keywords(self, flavor, data, options={}): - """ - Extracts the keywords from text, a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/keyword-extraction/ - For the docs, please refer to: http://www.alchemyapi.com/api/keyword-extraction/ - - INPUT: - flavor -> which version of the call, i.e. text, url or html. - data -> the data to analyze, either the text, the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - keywordExtractMode -> normal (default), strict - sentiment -> analyze sentiment for each keyword. 0: disabled (default), 1: enabled. Requires 1 additional API transaction if enabled. - showSourceText -> 0: disabled (default), 1: enabled. - maxRetrieve -> the max number of keywords returned (default: 50) - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['keywords']: - return { 'status':'ERROR', 'statusInfo':'keyword extraction for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['keywords'][flavor], {}, options) - - - - def concepts(self, flavor, data, options={}): - """ - Tags the concepts for text, a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/concept-tagging/ - For the docs, please refer to: http://www.alchemyapi.com/api/concept-tagging/ - - Available Options: - maxRetrieve -> the maximum number of concepts to retrieve (default: 8) - linkedData -> include linked data, 0: disabled, 1: enabled (default) - showSourceText -> 0:disabled (default), 1: enabled - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['concepts']: - return { 'status':'ERROR', 'statusInfo':'concept tagging for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['concepts'][flavor], {}, options) - - - - def sentiment(self, flavor, data, options={}): - """ - Calculates the sentiment for text, a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/sentiment-analysis/ - For the docs, please refer to: http://www.alchemyapi.com/api/sentiment-analysis/ - - INPUT: - flavor -> which version of the call, i.e. text, url or html. - data -> the data to analyze, either the text, the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - showSourceText -> 0: disabled (default), 1: enabled - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['sentiment']: - return { 'status':'ERROR', 'statusInfo':'sentiment analysis for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['sentiment'][flavor], {}, options) - - - - def sentiment_targeted(self, flavor, data, target, options={}): - """ - Calculates the targeted sentiment for text, a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/sentiment-analysis/ - For the docs, please refer to: http://www.alchemyapi.com/api/sentiment-analysis/ - - INPUT: - flavor -> which version of the call, i.e. text, url or html. - data -> the data to analyze, either the text, the url or html code. - target -> the word or phrase to run sentiment analysis on. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - showSourceText -> 0: disabled, 1: enabled - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure the target is valid - if target is None or target == '': - return { 'status':'ERROR', 'statusInfo':'targeted sentiment requires a non-null target' } - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['sentiment_targeted']: - return { 'status':'ERROR', 'statusInfo':'targeted sentiment analysis for ' + flavor + ' not available' } - - #add the URL encoded data and target to the options and analyze - options[flavor] = data - options['target'] = target - return self.__analyze(AlchemyAPI.ENDPOINTS['sentiment_targeted'][flavor], {}, options) - - - - def text(self, flavor, data, options={}): - """ - Extracts the cleaned text (removes ads, navigation, etc.) for text, a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/text-extraction/ - For the docs, please refer to: http://www.alchemyapi.com/api/text-extraction/ - - INPUT: - flavor -> which version of the call, i.e. text, url or html. - data -> the data to analyze, either the text, the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - useMetadata -> utilize meta description data, 0: disabled, 1: enabled (default) - extractLinks -> include links, 0: disabled (default), 1: enabled. - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['text']: - return { 'status':'ERROR', 'statusInfo':'clean text extraction for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['text'][flavor], options) - - - - def text_raw(self, flavor, data, options={}): - """ - Extracts the raw text (includes ads, navigation, etc.) for a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/text-extraction/ - For the docs, please refer to: http://www.alchemyapi.com/api/text-extraction/ - - INPUT: - flavor -> which version of the call, i.e. text, url or html. - data -> the data to analyze, either the text, the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - none - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['text_raw']: - return { 'status':'ERROR', 'statusInfo':'raw text extraction for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['text_raw'][flavor], {}, options) - - - - def author(self, flavor, data, options={}): - """ - Extracts the author from a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/author-extraction/ - For the docs, please refer to: http://www.alchemyapi.com/api/author-extraction/ - - INPUT: - flavor -> which version of the call, i.e. text, url or html. - data -> the data to analyze, either the text, the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Availble Options: - none - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['author']: - return { 'status':'ERROR', 'statusInfo':'author extraction for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['author'][flavor], {}, options) - - - - def language(self, flavor, data, options={}): - """ - Detects the language for text, a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/api/language-detection/ - For the docs, please refer to: http://www.alchemyapi.com/products/features/language-detection/ - - INPUT: - flavor -> which version of the call, i.e. text, url or html. - data -> the data to analyze, either the text, the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - none - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['language']: - return { 'status':'ERROR', 'statusInfo':'language detection for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['language'][flavor], {}, options) - - - - def title(self, flavor, data, options={}): - """ - Extracts the title for a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/text-extraction/ - For the docs, please refer to: http://www.alchemyapi.com/api/text-extraction/ - - INPUT: - flavor -> which version of the call, i.e. text, url or html. - data -> the data to analyze, either the text, the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - useMetadata -> utilize title info embedded in meta data, 0: disabled, 1: enabled (default) - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['title']: - return { 'status':'ERROR', 'statusInfo':'title extraction for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['title'][flavor], {}, options) - - - - def relations(self, flavor, data, options={}): - """ - Extracts the relations for text, a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/relation-extraction/ - For the docs, please refer to: http://www.alchemyapi.com/api/relation-extraction/ - - INPUT: - flavor -> which version of the call, i.e. text, url or html. - data -> the data to analyze, either the text, the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - sentiment -> 0: disabled (default), 1: enabled. Requires one additional API transaction if enabled. - keywords -> extract keywords from the subject and object. 0: disabled (default), 1: enabled. Requires one additional API transaction if enabled. - entities -> extract entities from the subject and object. 0: disabled (default), 1: enabled. Requires one additional API transaction if enabled. - requireEntities -> only extract relations that have entities. 0: disabled (default), 1: enabled. - sentimentExcludeEntities -> exclude full entity name in sentiment analysis. 0: disabled, 1: enabled (default) - disambiguate -> disambiguate entities (i.e. Apple the company vs. apple the fruit). 0: disabled, 1: enabled (default) - linkedData -> include linked data with disambiguated entities. 0: disabled, 1: enabled (default). - coreference -> resolve entity coreferences. 0: disabled, 1: enabled (default) - showSourceText -> 0: disabled (default), 1: enabled. - maxRetrieve -> the maximum number of relations to extract (default: 50, max: 100) - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['relations']: - return { 'status':'ERROR', 'statusInfo':'relation extraction for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['relations'][flavor], {}, options) - - - - def category(self, flavor, data, options={}): - """ - Categorizes the text for text, a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/text-categorization/ - For the docs, please refer to: http://www.alchemyapi.com/api/text-categorization/ - - INPUT: - flavor -> which version of the call, i.e. text, url or html. - data -> the data to analyze, either the text, the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - showSourceText -> 0: disabled (default), 1: enabled - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['category']: - return { 'status':'ERROR', 'statusInfo':'text categorization for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - - return self.__analyze(AlchemyAPI.ENDPOINTS['category'][flavor], {}, options) - - - - def feeds(self, flavor, data, options={}): - """ - Detects the RSS/ATOM feeds for a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/feed-detection/ - For the docs, please refer to: http://www.alchemyapi.com/api/feed-detection/ - - INPUT: - flavor -> which version of the call, i.e. url or html. - data -> the data to analyze, either the the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - none - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['feeds']: - return { 'status':'ERROR', 'statusInfo':'feed detection for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['feeds'][flavor], {}, options) - - - - def microformats(self, flavor, data, options={}): - """ - Parses the microformats for a URL or HTML. - For an overview, please refer to: http://www.alchemyapi.com/products/features/microformats-parsing/ - For the docs, please refer to: http://www.alchemyapi.com/api/microformats-parsing/ - - INPUT: - flavor -> which version of the call, i.e. url or html. - data -> the data to analyze, either the the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - none - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Make sure this request supports this flavor - if flavor not in AlchemyAPI.ENDPOINTS['microformats']: - return { 'status':'ERROR', 'statusInfo':'microformat extraction for ' + flavor + ' not available' } - - #add the data to the options and analyze - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['microformats'][flavor], {}, options) - - def imageExtraction(self, flavor, data, options={}): - """ - Extracts main image from a URL - - INPUT: - flavor -> which version of the call (url only currently). - data -> URL to analyze - options -> various parameters that can be used to adjust how the API works, - see below for more info on the available options. - - Available Options: - extractMode -> - trust-metadata : (less CPU intensive, less accurate) - always-infer : (more CPU intensive, more accurate) - OUTPUT: - The response, already converted from JSON to a Python object. - """ - if flavor not in AlchemyAPI.ENDPOINTS['image']: - return { 'status':'ERROR', 'statusInfo':'image extraction for ' + flavor + ' not available' } - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['image'][flavor], {}, options) - - def taxonomy(self, flavor, data, options={}): - """ - Taxonomy classification operations. - - INPUT: - flavor -> which version of the call, i.e. url or html. - data -> the data to analyze, either the the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - - Available Options: - showSourceText -> - include the original 'source text' the taxonomy categories were extracted from within the API response - Possible values: - 1 - enabled - 0 - disabled (default) - - sourceText -> - where to obtain the text that will be processed by this API call. - - AlchemyAPI supports multiple modes of text extraction: - web page cleaning (removes ads, navigation links, etc.), raw text extraction - (processes all web page text, including ads / nav links), visual constraint queries, and XPath queries. - - Possible values: - cleaned_or_raw : cleaning enabled, fallback to raw when cleaning produces no text (default) - cleaned : operate on 'cleaned' web page text (web page cleaning enabled) - raw : operate on raw web page text (web page cleaning disabled) - cquery : operate on the results of a visual constraints query - Note: The 'cquery' http argument must also be set to a valid visual constraints query. - xpath : operate on the results of an XPath query - Note: The 'xpath' http argument must also be set to a valid XPath query. - - cquery -> - a visual constraints query to apply to the web page. - - xpath -> - an XPath query to apply to the web page. - - baseUrl -> - rel-tag output base http url (must be uri-argument encoded) - - OUTPUT: - The response, already converted from JSON to a Python object. - - """ - if flavor not in AlchemyAPI.ENDPOINTS['taxonomy']: - return { 'status':'ERROR', 'statusInfo':'taxonomy for ' + flavor + ' not available' } - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['taxonomy'][flavor], {}, options) - - def combined(self, flavor, data, options={}): - """ - Combined call for page-image, entity, keyword, title, author, taxonomy, concept. - - INPUT: - flavor -> which version of the call, i.e. url or html. - data -> the data to analyze, either the the url or html code. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - - Available Options: - extract -> - Possible values: page-image, entity, keyword, title, author, taxonomy, concept - default : entity, keyword, taxonomy, concept - - disambiguate -> - disambiguate detected entities - Possible values: - 1 : enabled (default) - 0 : disabled - - linkedData -> - include Linked Data content links with disambiguated entities - Possible values : - 1 : enabled (default) - 0 : disabled - - coreference -> - resolve he/she/etc coreferences into detected entities - Possible values: - 1 : enabled (default) - 0 : disabled - - quotations -> - enable quotations extraction - Possible values: - 1 : enabled - 0 : disabled (default) - - sentiment -> - enable entity-level sentiment analysis - Possible values: - 1 : enabled - 0 : disabled (default) - - showSourceText -> - include the original 'source text' the entities were extracted from within the API response - Possible values: - 1 : enabled - 0 : disabled (default) - - maxRetrieve -> - maximum number of named entities to extract - default : 50 - - baseUrl -> - rel-tag output base http url - - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - if flavor not in AlchemyAPI.ENDPOINTS['combined']: - return { 'status':'ERROR', 'statusInfo':'combined for ' + flavor + ' not available' } - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['combined'][flavor], {}, options) - - def imageTagging(self, flavor, data, options={}): - """ - - INPUT: - flavor -> which version of the call only url or image. - data -> the data to analyze, either the the url or path to image. - options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. - """ - if flavor not in AlchemyAPI.ENDPOINTS['imagetagging']: - return { 'status':'ERROR', 'statusInfo':'imagetagging for ' + flavor + ' not available' } - elif 'image' == flavor: - image = open(data, 'rb').read() - options['imagePostMode'] = 'raw' - return self.__analyze(AlchemyAPI.ENDPOINTS['imagetagging'][flavor], options, image) - - options[flavor] = data - return self.__analyze(AlchemyAPI.ENDPOINTS['imagetagging'][flavor], {}, options) - - - def __analyze(self, endpoint, params, post_data=bytearray()): - """ - HTTP Request wrapper that is called by the endpoint functions. This function is not intended to be called through an external interface. - It makes the call, then converts the returned JSON string into a Python object. - - INPUT: - url -> the full URI encoded url - - OUTPUT: - The response, already converted from JSON to a Python object. - """ - - #Add the API Key and set the output mode to JSON - params['apikey'] = self.apikey; - params['outputMode'] = 'json'; - #Insert the base url - - post_url = AlchemyAPI.BASE_URL + endpoint + '?' + urlencode(params).encode('utf-8'); - - try: - results = self.s.post(url=post_url, data=post_data) - return results.json() - except Exception as e: - print(e) - return { 'status':'ERROR', 'statusInfo':'network-error' } - + # Setup the endpoints + ENDPOINTS = {} + ENDPOINTS['sentiment'] = {} + ENDPOINTS['sentiment']['url'] = '/url/URLGetTextSentiment' + ENDPOINTS['sentiment']['text'] = '/text/TextGetTextSentiment' + ENDPOINTS['sentiment']['html'] = '/html/HTMLGetTextSentiment' + ENDPOINTS['sentiment_targeted'] = {} + ENDPOINTS['sentiment_targeted']['url'] = '/url/URLGetTargetedSentiment' + ENDPOINTS['sentiment_targeted']['text'] = '/text/TextGetTargetedSentiment' + ENDPOINTS['sentiment_targeted']['html'] = '/html/HTMLGetTargetedSentiment' + ENDPOINTS['author'] = {} + ENDPOINTS['author']['url'] = '/url/URLGetAuthor' + ENDPOINTS['author']['html'] = '/html/HTMLGetAuthor' + ENDPOINTS['keywords'] = {} + ENDPOINTS['keywords']['url'] = '/url/URLGetRankedKeywords' + ENDPOINTS['keywords']['text'] = '/text/TextGetRankedKeywords' + ENDPOINTS['keywords']['html'] = '/html/HTMLGetRankedKeywords' + ENDPOINTS['concepts'] = {} + ENDPOINTS['concepts']['url'] = '/url/URLGetRankedConcepts' + ENDPOINTS['concepts']['text'] = '/text/TextGetRankedConcepts' + ENDPOINTS['concepts']['html'] = '/html/HTMLGetRankedConcepts' + ENDPOINTS['entities'] = {} + ENDPOINTS['entities']['url'] = '/url/URLGetRankedNamedEntities' + ENDPOINTS['entities']['text'] = '/text/TextGetRankedNamedEntities' + ENDPOINTS['entities']['html'] = '/html/HTMLGetRankedNamedEntities' + ENDPOINTS['category'] = {} + ENDPOINTS['category']['url'] = '/url/URLGetCategory' + ENDPOINTS['category']['text'] = '/text/TextGetCategory' + ENDPOINTS['category']['html'] = '/html/HTMLGetCategory' + ENDPOINTS['relations'] = {} + ENDPOINTS['relations']['url'] = '/url/URLGetRelations' + ENDPOINTS['relations']['text'] = '/text/TextGetRelations' + ENDPOINTS['relations']['html'] = '/html/HTMLGetRelations' + ENDPOINTS['language'] = {} + ENDPOINTS['language']['url'] = '/url/URLGetLanguage' + ENDPOINTS['language']['text'] = '/text/TextGetLanguage' + ENDPOINTS['language']['html'] = '/html/HTMLGetLanguage' + ENDPOINTS['text'] = {} + ENDPOINTS['text']['url'] = '/url/URLGetText' + ENDPOINTS['text']['html'] = '/html/HTMLGetText' + ENDPOINTS['text_raw'] = {} + ENDPOINTS['text_raw']['url'] = '/url/URLGetRawText' + ENDPOINTS['text_raw']['html'] = '/html/HTMLGetRawText' + ENDPOINTS['title'] = {} + ENDPOINTS['title']['url'] = '/url/URLGetTitle' + ENDPOINTS['title']['html'] = '/html/HTMLGetTitle' + ENDPOINTS['feeds'] = {} + ENDPOINTS['feeds']['url'] = '/url/URLGetFeedLinks' + ENDPOINTS['feeds']['html'] = '/html/HTMLGetFeedLinks' + ENDPOINTS['microformats'] = {} + ENDPOINTS['microformats']['url'] = '/url/URLGetMicroformatData' + ENDPOINTS['microformats']['html'] = '/html/HTMLGetMicroformatData' + ENDPOINTS['combined'] = {} + ENDPOINTS['combined']['url'] = '/url/URLGetCombinedData' + ENDPOINTS['combined']['text'] = '/text/TextGetCombinedData' + ENDPOINTS['image'] = {} + ENDPOINTS['image']['url'] = '/url/URLGetImage' + ENDPOINTS['imagetagging'] = {} + ENDPOINTS['imagetagging']['url'] = '/url/URLGetRankedImageKeywords' + ENDPOINTS['imagetagging']['image'] = '/image/ImageGetRankedImageKeywords' + ENDPOINTS['taxonomy'] = {} + ENDPOINTS['taxonomy']['url'] = '/url/URLGetRankedTaxonomy' + ENDPOINTS['taxonomy']['html'] = '/html/HTMLGetRankedTaxonomy' + ENDPOINTS['taxonomy']['text'] = '/text/TextGetRankedTaxonomy' + + # The base URL for all endpoints + BASE_URL = 'http://access.alchemyapi.com/calls' + + s = requests.Session() + + def __init__(self): + """ + Initializes the SDK so it can send requests to AlchemyAPI for analysis. + It loads the API key from api_key.txt and configures the endpoints. + """ + + import sys + try: + # Open the key file and read the key + f = open("api_key.txt", "r") + key = f.read().strip() + + if key == '': + # The key file should't be blank + print( + 'The api_key.txt file appears to be blank, please run: python alchemyapi.py YOUR_KEY_HERE') + print( + 'If you do not have an API Key from AlchemyAPI, please register for one at: http://www.alchemyapi.com/api/register.html') + sys.exit(0) + elif len(key) != 40: + # Keys should be exactly 40 characters long + print( + 'It appears that the key in api_key.txt is invalid. Please make sure the file only includes the API key, and it is the correct one.') + sys.exit(0) + else: + # setup the key + self.apikey = key + + # Close file + f.close() + except IOError: + # The file doesn't exist, so show the message and create the file. + print( + 'API Key not found! Please run: python alchemyapi.py YOUR_KEY_HERE') + print( + 'If you do not have an API Key from AlchemyAPI, please register for one at: http://www.alchemyapi.com/api/register.html') + + # create a blank key file + open('api_key.txt', 'a').close() + sys.exit(0) + except Exception as e: + print(e) + + def entities(self, flavor, data, options={}): + """ + Extracts the entities for text, a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/entity-extraction/ + For the docs, please refer to: http://www.alchemyapi.com/api/entity-extraction/ + + INPUT: + flavor -> which version of the call, i.e. text, url or html. + data -> the data to analyze, either the text, the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + disambiguate -> disambiguate entities (i.e. Apple the company vs. apple the fruit). 0: disabled, 1: enabled (default) + linkedData -> include linked data on disambiguated entities. 0: disabled, 1: enabled (default) + coreference -> resolve coreferences (i.e. the pronouns that correspond to named entities). 0: disabled, 1: enabled (default) + quotations -> extract quotations by entities. 0: disabled (default), 1: enabled. + sentiment -> analyze sentiment for each entity. 0: disabled (default), 1: enabled. Requires 1 additional API transction if enabled. + showSourceText -> 0: disabled (default), 1: enabled + maxRetrieve -> the maximum number of entities to retrieve (default: 50) + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['entities']: + return {'status': 'ERROR', 'statusInfo': 'entity extraction for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['entities'][flavor], {}, options) + + def keywords(self, flavor, data, options={}): + """ + Extracts the keywords from text, a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/keyword-extraction/ + For the docs, please refer to: http://www.alchemyapi.com/api/keyword-extraction/ + + INPUT: + flavor -> which version of the call, i.e. text, url or html. + data -> the data to analyze, either the text, the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + keywordExtractMode -> normal (default), strict + sentiment -> analyze sentiment for each keyword. 0: disabled (default), 1: enabled. Requires 1 additional API transaction if enabled. + showSourceText -> 0: disabled (default), 1: enabled. + maxRetrieve -> the max number of keywords returned (default: 50) + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['keywords']: + return {'status': 'ERROR', 'statusInfo': 'keyword extraction for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['keywords'][flavor], {}, options) + + def concepts(self, flavor, data, options={}): + """ + Tags the concepts for text, a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/concept-tagging/ + For the docs, please refer to: http://www.alchemyapi.com/api/concept-tagging/ + + Available Options: + maxRetrieve -> the maximum number of concepts to retrieve (default: 8) + linkedData -> include linked data, 0: disabled, 1: enabled (default) + showSourceText -> 0:disabled (default), 1: enabled + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['concepts']: + return {'status': 'ERROR', 'statusInfo': 'concept tagging for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['concepts'][flavor], {}, options) + + def sentiment(self, flavor, data, options={}): + """ + Calculates the sentiment for text, a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/sentiment-analysis/ + For the docs, please refer to: http://www.alchemyapi.com/api/sentiment-analysis/ + + INPUT: + flavor -> which version of the call, i.e. text, url or html. + data -> the data to analyze, either the text, the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + showSourceText -> 0: disabled (default), 1: enabled + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['sentiment']: + return {'status': 'ERROR', 'statusInfo': 'sentiment analysis for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['sentiment'][flavor], {}, options) + + def sentiment_targeted(self, flavor, data, target, options={}): + """ + Calculates the targeted sentiment for text, a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/sentiment-analysis/ + For the docs, please refer to: http://www.alchemyapi.com/api/sentiment-analysis/ + + INPUT: + flavor -> which version of the call, i.e. text, url or html. + data -> the data to analyze, either the text, the url or html code. + target -> the word or phrase to run sentiment analysis on. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + showSourceText -> 0: disabled, 1: enabled + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure the target is valid + if target is None or target == '': + return {'status': 'ERROR', 'statusInfo': 'targeted sentiment requires a non-null target'} + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['sentiment_targeted']: + return {'status': 'ERROR', 'statusInfo': 'targeted sentiment analysis for ' + flavor + ' not available'} + + # add the URL encoded data and target to the options and analyze + options[flavor] = data + options['target'] = target + return self.__analyze(AlchemyAPI.ENDPOINTS['sentiment_targeted'][flavor], {}, options) + + def text(self, flavor, data, options={}): + """ + Extracts the cleaned text (removes ads, navigation, etc.) for text, a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/text-extraction/ + For the docs, please refer to: http://www.alchemyapi.com/api/text-extraction/ + + INPUT: + flavor -> which version of the call, i.e. text, url or html. + data -> the data to analyze, either the text, the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + useMetadata -> utilize meta description data, 0: disabled, 1: enabled (default) + extractLinks -> include links, 0: disabled (default), 1: enabled. + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['text']: + return {'status': 'ERROR', 'statusInfo': 'clean text extraction for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['text'][flavor], options) + + def text_raw(self, flavor, data, options={}): + """ + Extracts the raw text (includes ads, navigation, etc.) for a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/text-extraction/ + For the docs, please refer to: http://www.alchemyapi.com/api/text-extraction/ + + INPUT: + flavor -> which version of the call, i.e. text, url or html. + data -> the data to analyze, either the text, the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + none + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['text_raw']: + return {'status': 'ERROR', 'statusInfo': 'raw text extraction for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['text_raw'][flavor], {}, options) + + def author(self, flavor, data, options={}): + """ + Extracts the author from a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/author-extraction/ + For the docs, please refer to: http://www.alchemyapi.com/api/author-extraction/ + + INPUT: + flavor -> which version of the call, i.e. text, url or html. + data -> the data to analyze, either the text, the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Availble Options: + none + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['author']: + return {'status': 'ERROR', 'statusInfo': 'author extraction for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['author'][flavor], {}, options) + + def language(self, flavor, data, options={}): + """ + Detects the language for text, a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/api/language-detection/ + For the docs, please refer to: http://www.alchemyapi.com/products/features/language-detection/ + + INPUT: + flavor -> which version of the call, i.e. text, url or html. + data -> the data to analyze, either the text, the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + none + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['language']: + return {'status': 'ERROR', 'statusInfo': 'language detection for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['language'][flavor], {}, options) + + def title(self, flavor, data, options={}): + """ + Extracts the title for a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/text-extraction/ + For the docs, please refer to: http://www.alchemyapi.com/api/text-extraction/ + + INPUT: + flavor -> which version of the call, i.e. text, url or html. + data -> the data to analyze, either the text, the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + useMetadata -> utilize title info embedded in meta data, 0: disabled, 1: enabled (default) + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['title']: + return {'status': 'ERROR', 'statusInfo': 'title extraction for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['title'][flavor], {}, options) + + def relations(self, flavor, data, options={}): + """ + Extracts the relations for text, a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/relation-extraction/ + For the docs, please refer to: http://www.alchemyapi.com/api/relation-extraction/ + + INPUT: + flavor -> which version of the call, i.e. text, url or html. + data -> the data to analyze, either the text, the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + sentiment -> 0: disabled (default), 1: enabled. Requires one additional API transaction if enabled. + keywords -> extract keywords from the subject and object. 0: disabled (default), 1: enabled. Requires one additional API transaction if enabled. + entities -> extract entities from the subject and object. 0: disabled (default), 1: enabled. Requires one additional API transaction if enabled. + requireEntities -> only extract relations that have entities. 0: disabled (default), 1: enabled. + sentimentExcludeEntities -> exclude full entity name in sentiment analysis. 0: disabled, 1: enabled (default) + disambiguate -> disambiguate entities (i.e. Apple the company vs. apple the fruit). 0: disabled, 1: enabled (default) + linkedData -> include linked data with disambiguated entities. 0: disabled, 1: enabled (default). + coreference -> resolve entity coreferences. 0: disabled, 1: enabled (default) + showSourceText -> 0: disabled (default), 1: enabled. + maxRetrieve -> the maximum number of relations to extract (default: 50, max: 100) + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['relations']: + return {'status': 'ERROR', 'statusInfo': 'relation extraction for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['relations'][flavor], {}, options) + + def category(self, flavor, data, options={}): + """ + Categorizes the text for text, a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/text-categorization/ + For the docs, please refer to: http://www.alchemyapi.com/api/text-categorization/ + + INPUT: + flavor -> which version of the call, i.e. text, url or html. + data -> the data to analyze, either the text, the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + showSourceText -> 0: disabled (default), 1: enabled + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['category']: + return {'status': 'ERROR', 'statusInfo': 'text categorization for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + + return self.__analyze(AlchemyAPI.ENDPOINTS['category'][flavor], {}, options) + + def feeds(self, flavor, data, options={}): + """ + Detects the RSS/ATOM feeds for a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/feed-detection/ + For the docs, please refer to: http://www.alchemyapi.com/api/feed-detection/ + + INPUT: + flavor -> which version of the call, i.e. url or html. + data -> the data to analyze, either the the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + none + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['feeds']: + return {'status': 'ERROR', 'statusInfo': 'feed detection for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['feeds'][flavor], {}, options) + + def microformats(self, flavor, data, options={}): + """ + Parses the microformats for a URL or HTML. + For an overview, please refer to: http://www.alchemyapi.com/products/features/microformats-parsing/ + For the docs, please refer to: http://www.alchemyapi.com/api/microformats-parsing/ + + INPUT: + flavor -> which version of the call, i.e. url or html. + data -> the data to analyze, either the the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + none + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Make sure this request supports this flavor + if flavor not in AlchemyAPI.ENDPOINTS['microformats']: + return {'status': 'ERROR', 'statusInfo': 'microformat extraction for ' + flavor + ' not available'} + + # add the data to the options and analyze + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['microformats'][flavor], {}, options) + + def imageExtraction(self, flavor, data, options={}): + """ + Extracts main image from a URL + + INPUT: + flavor -> which version of the call (url only currently). + data -> URL to analyze + options -> various parameters that can be used to adjust how the API works, + see below for more info on the available options. + + Available Options: + extractMode -> + trust-metadata : (less CPU intensive, less accurate) + always-infer : (more CPU intensive, more accurate) + OUTPUT: + The response, already converted from JSON to a Python object. + """ + if flavor not in AlchemyAPI.ENDPOINTS['image']: + return {'status': 'ERROR', 'statusInfo': 'image extraction for ' + flavor + ' not available'} + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['image'][flavor], {}, options) + + def taxonomy(self, flavor, data, options={}): + """ + Taxonomy classification operations. + + INPUT: + flavor -> which version of the call, i.e. url or html. + data -> the data to analyze, either the the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + + Available Options: + showSourceText -> + include the original 'source text' the taxonomy categories were extracted from within the API response + Possible values: + 1 - enabled + 0 - disabled (default) + + sourceText -> + where to obtain the text that will be processed by this API call. + + AlchemyAPI supports multiple modes of text extraction: + web page cleaning (removes ads, navigation links, etc.), raw text extraction + (processes all web page text, including ads / nav links), visual constraint queries, and XPath queries. + + Possible values: + cleaned_or_raw : cleaning enabled, fallback to raw when cleaning produces no text (default) + cleaned : operate on 'cleaned' web page text (web page cleaning enabled) + raw : operate on raw web page text (web page cleaning disabled) + cquery : operate on the results of a visual constraints query + Note: The 'cquery' http argument must also be set to a valid visual constraints query. + xpath : operate on the results of an XPath query + Note: The 'xpath' http argument must also be set to a valid XPath query. + + cquery -> + a visual constraints query to apply to the web page. + + xpath -> + an XPath query to apply to the web page. + + baseUrl -> + rel-tag output base http url (must be uri-argument encoded) + + OUTPUT: + The response, already converted from JSON to a Python object. + + """ + if flavor not in AlchemyAPI.ENDPOINTS['taxonomy']: + return {'status': 'ERROR', 'statusInfo': 'taxonomy for ' + flavor + ' not available'} + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['taxonomy'][flavor], {}, options) + + def combined(self, flavor, data, options={}): + """ + Combined call for page-image, entity, keyword, title, author, taxonomy, concept. + + INPUT: + flavor -> which version of the call, i.e. url or html. + data -> the data to analyze, either the the url or html code. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + + Available Options: + extract -> + Possible values: page-image, entity, keyword, title, author, taxonomy, concept + default : entity, keyword, taxonomy, concept + + disambiguate -> + disambiguate detected entities + Possible values: + 1 : enabled (default) + 0 : disabled + + linkedData -> + include Linked Data content links with disambiguated entities + Possible values : + 1 : enabled (default) + 0 : disabled + + coreference -> + resolve he/she/etc coreferences into detected entities + Possible values: + 1 : enabled (default) + 0 : disabled + + quotations -> + enable quotations extraction + Possible values: + 1 : enabled + 0 : disabled (default) + + sentiment -> + enable entity-level sentiment analysis + Possible values: + 1 : enabled + 0 : disabled (default) + + showSourceText -> + include the original 'source text' the entities were extracted from within the API response + Possible values: + 1 : enabled + 0 : disabled (default) + + maxRetrieve -> + maximum number of named entities to extract + default : 50 + + baseUrl -> + rel-tag output base http url + + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + if flavor not in AlchemyAPI.ENDPOINTS['combined']: + return {'status': 'ERROR', 'statusInfo': 'combined for ' + flavor + ' not available'} + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['combined'][flavor], {}, options) + + def imageTagging(self, flavor, data, options={}): + """ + + INPUT: + flavor -> which version of the call only url or image. + data -> the data to analyze, either the the url or path to image. + options -> various parameters that can be used to adjust how the API works, see below for more info on the available options. + """ + if flavor not in AlchemyAPI.ENDPOINTS['imagetagging']: + return {'status': 'ERROR', 'statusInfo': 'imagetagging for ' + flavor + ' not available'} + elif 'image' == flavor: + image = open(data, 'rb').read() + options['imagePostMode'] = 'raw' + return self.__analyze(AlchemyAPI.ENDPOINTS['imagetagging'][flavor], options, image) + + options[flavor] = data + return self.__analyze(AlchemyAPI.ENDPOINTS['imagetagging'][flavor], {}, options) + + def __analyze(self, endpoint, params, post_data=bytearray()): + """ + HTTP Request wrapper that is called by the endpoint functions. This function is not intended to be called through an external interface. + It makes the call, then converts the returned JSON string into a Python object. + + INPUT: + url -> the full URI encoded url + + OUTPUT: + The response, already converted from JSON to a Python object. + """ + + # Add the API Key and set the output mode to JSON + params['apikey'] = self.apikey + params['outputMode'] = 'json' + # Insert the base url + + post_url = AlchemyAPI.BASE_URL + endpoint + \ + '?' + urlencode(params).encode('utf-8') + + try: + results = self.s.post(url=post_url, data=post_data) + return results.json() + except Exception as e: + print(e) + return {'status': 'ERROR', 'statusInfo': 'network-error'} diff --git a/example.py b/example.py index a49e1a4..854ce89 100644 --- a/example.py +++ b/example.py @@ -27,30 +27,51 @@ print('') print('') -print(' , ') -print(' .I7777~ ') -print(' .I7777777 ') -print(' +. 77777777 ') -print(' =???, I7777777= ') -print('=?????? 7777777? ,:::===? ') -print('=???????. 777777777777777777~ .77: ?? :7 =$, :$$$$$$+ =$? ') -print(' ????????: .777777777777777777 II77 ?? :7 $$7 :$? 7$7 =$? ') -print(' .???????= +7777777777777777 .7 =7: ?? :7777+ :7:I777? ?777I= 77~777? ,777I I7 77 +$?$: :$? $$ =$? ') -print(' ???????+ ~777???+===::: :7+ ~7 ?? .77 +7 :7?. II 7~ ,I7 77+ I77 ~7 ?7 =7: .$, =$ :$? ,$$? =$? ') -print(' ,???????~ 77 7: ?? ?I. 7 :7 :7 ~7 7 77 =7: 7 7 7~ 7$ $= :$$$$$$~ =$? ') -print(' .??????? ,???I77777777777~ :77777777~ ?? 7: :7 :7 777777777:77 =7 7 +7 ~7 $$$$$$$$I :$? =$? ') -print(' .??????? ,7777777777777777 7= 77 ?? I+ 7 :7 :7 ?? 7,77 =7 7 7~ 7, =$7 $$, :$? =$? ') -print(' .???????. I77777777777777777 +7 ,7??? 77 I7 :7 :7 7~ .?7 77 =7 7 ,77I $+ 7$ :$? =$? ') -print(' ,???????= :77777777777777777~ 7= ~7?? ~I77777 :7 :7 ,777777. 77 =7 7 77, +$ .$::$? =$? ') -print(',??????? :7777777 77 ') -print(' =????? ,7777777 77= ') -print(' +?+ 7777777? ') -print(' + ~7777777 ') -print(' I777777 ') -print(' :~ ') - - -#Create the AlchemyAPI Object +print( + ' , ') +print( + ' .I7777~ ') +print( + ' .I7777777 ') +print( + ' +. 77777777 ') +print( + ' =???, I7777777= ') +print( + '=?????? 7777777? ,:::===? ') +print( + '=???????. 777777777777777777~ .77: ?? :7 =$, :$$$$$$+ =$? ') +print( + ' ????????: .777777777777777777 II77 ?? :7 $$7 :$? 7$7 =$? ') +print( + ' .???????= +7777777777777777 .7 =7: ?? :7777+ :7:I777? ?777I= 77~777? ,777I I7 77 +$?$: :$? $$ =$? ') +print( + ' ???????+ ~777???+===::: :7+ ~7 ?? .77 +7 :7?. II 7~ ,I7 77+ I77 ~7 ?7 =7: .$, =$ :$? ,$$? =$? ') +print( + ' ,???????~ 77 7: ?? ?I. 7 :7 :7 ~7 7 77 =7: 7 7 7~ 7$ $= :$$$$$$~ =$? ') +print( + ' .??????? ,???I77777777777~ :77777777~ ?? 7: :7 :7 777777777:77 =7 7 +7 ~7 $$$$$$$$I :$? =$? ') +print( + ' .??????? ,7777777777777777 7= 77 ?? I+ 7 :7 :7 ?? 7,77 =7 7 7~ 7, =$7 $$, :$? =$? ') +print( + ' .???????. I77777777777777777 +7 ,7??? 77 I7 :7 :7 7~ .?7 77 =7 7 ,77I $+ 7$ :$? =$? ') +print( + ' ,???????= :77777777777777777~ 7= ~7?? ~I77777 :7 :7 ,777777. 77 =7 7 77, +$ .$::$? =$? ') +print( + ',??????? :7777777 77 ') +print( + ' =????? ,7777777 77= ') +print( + ' +?+ 7777777? ') +print( + ' + ~7777777 ') +print( + ' I777777 ') +print( + ' :~ ') + + +# Create the AlchemyAPI Object alchemyapi = AlchemyAPI() print('') @@ -58,32 +79,30 @@ print('############################################') print('# Entity Extraction Example #') print('############################################') -print('') +print('') print('') print('Processing text: ', demo_text) print('') -response = alchemyapi.entities('text',demo_text, { 'sentiment':1 }) +response = alchemyapi.entities('text', demo_text, {'sentiment': 1}) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) - - - print('') - print('## Entities ##') - for entity in response['entities']: - print('text: ', entity['text'].encode('utf-8')) - print('type: ', entity['type']) - print('relevance: ', entity['relevance']) - print('sentiment: ', entity['sentiment']['type']) - if 'score' in entity['sentiment']: - print('sentiment score: ' + entity['sentiment']['score']) - print('') + print('## Response Object ##') + print(json.dumps(response, indent=4)) + + print('') + print('## Entities ##') + for entity in response['entities']: + print('text: ', entity['text'].encode('utf-8')) + print('type: ', entity['type']) + print('relevance: ', entity['relevance']) + print('sentiment: ', entity['sentiment']['type']) + if 'score' in entity['sentiment']: + print('sentiment score: ' + entity['sentiment']['score']) + print('') else: - print('Error in entity extraction call: ', response['statusInfo']) - + print('Error in entity extraction call: ', response['statusInfo']) print('') @@ -98,25 +117,23 @@ print('Processing text: ', demo_text) print('') -response = alchemyapi.keywords('text',demo_text, { 'sentiment':1 }) +response = alchemyapi.keywords('text', demo_text, {'sentiment': 1}) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) - - - print('') - print('## Keywords ##') - for keyword in response['keywords']: - print('text: ', keyword['text'].encode('utf-8')) - print('relevance: ', keyword['relevance']) - print('sentiment: ', keyword['sentiment']['type']) - if 'score' in keyword['sentiment']: - print('sentiment score: ' + keyword['sentiment']['score']) - print('') + print('## Response Object ##') + print(json.dumps(response, indent=4)) + + print('') + print('## Keywords ##') + for keyword in response['keywords']: + print('text: ', keyword['text'].encode('utf-8')) + print('relevance: ', keyword['relevance']) + print('sentiment: ', keyword['sentiment']['type']) + if 'score' in keyword['sentiment']: + print('sentiment score: ' + keyword['sentiment']['score']) + print('') else: - print('Error in keyword extaction call: ', response['statusInfo']) - + print('Error in keyword extaction call: ', response['statusInfo']) print('') @@ -131,22 +148,20 @@ print('Processing text: ', demo_text) print('') -response = alchemyapi.concepts('text',demo_text) +response = alchemyapi.concepts('text', demo_text) if response['status'] == 'OK': - print('## Object ##') - print(json.dumps(response, indent=4)) - - - print('') - print('## Concepts ##') - for concept in response['concepts']: - print('text: ', concept['text']) - print('relevance: ', concept['relevance']) - print('') + print('## Object ##') + print(json.dumps(response, indent=4)) + + print('') + print('## Concepts ##') + for concept in response['concepts']: + print('text: ', concept['text']) + print('relevance: ', concept['relevance']) + print('') else: - print('Error in concept tagging call: ', response['statusInfo']) - + print('Error in concept tagging call: ', response['statusInfo']) print('') @@ -161,21 +176,20 @@ print('Processing html: ', demo_html) print('') -response = alchemyapi.sentiment('html',demo_html) +response = alchemyapi.sentiment('html', demo_html) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) - - print('') - print('## Document Sentiment ##') - print('type: ', response['docSentiment']['type']) - - if 'score' in response['docSentiment']: - print('score: ', response['docSentiment']['score']) -else: - print('Error in sentiment analysis call: ', response['statusInfo']) + print('## Response Object ##') + print(json.dumps(response, indent=4)) + + print('') + print('## Document Sentiment ##') + print('type: ', response['docSentiment']['type']) + if 'score' in response['docSentiment']: + print('score: ', response['docSentiment']['score']) +else: + print('Error in sentiment analysis call: ', response['statusInfo']) print('') @@ -190,21 +204,21 @@ print('Processing text: ', demo_text) print('') -response = alchemyapi.sentiment_targeted('text',demo_text, 'Denver') +response = alchemyapi.sentiment_targeted('text', demo_text, 'Denver') if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) - - print('') - print('## Targeted Sentiment ##') - print('type: ', response['docSentiment']['type']) - - if 'score' in response['docSentiment']: - print('score: ', response['docSentiment']['score']) -else: - print('Error in targeted sentiment analysis call: ', response['statusInfo']) + print('## Response Object ##') + print(json.dumps(response, indent=4)) + print('') + print('## Targeted Sentiment ##') + print('type: ', response['docSentiment']['type']) + + if 'score' in response['docSentiment']: + print('score: ', response['docSentiment']['score']) +else: + print('Error in targeted sentiment analysis call: ', + response['statusInfo']) print('') @@ -219,19 +233,18 @@ print('Processing url: ', demo_url) print('') -response = alchemyapi.text('url',demo_url) +response = alchemyapi.text('url', demo_url) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) + print('## Response Object ##') + print(json.dumps(response, indent=4)) - print('') - print('## Text ##') - print('text: ', response['text'].encode('utf-8')) - print('') + print('') + print('## Text ##') + print('text: ', response['text'].encode('utf-8')) + print('') else: - print('Error in text extraction call: ', response['statusInfo']) - + print('Error in text extraction call: ', response['statusInfo']) print('') @@ -246,19 +259,18 @@ print('Processing url: ', demo_url) print('') -response = alchemyapi.author('url',demo_url) +response = alchemyapi.author('url', demo_url) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) + print('## Response Object ##') + print(json.dumps(response, indent=4)) - print('') - print('## Author ##') - print('author: ', response['author'].encode('utf-8')) - print('') + print('') + print('## Author ##') + print('author: ', response['author'].encode('utf-8')) + print('') else: - print('Error in author extraction call: ', response['statusInfo']) - + print('Error in author extraction call: ', response['statusInfo']) print('') @@ -273,22 +285,20 @@ print('Processing text: ', demo_text) print('') -response = alchemyapi.language('text',demo_text) +response = alchemyapi.language('text', demo_text) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) - - - print('') - print('## Language ##') - print('language: ', response['language']) - print('iso-639-1: ', response['iso-639-1']) - print('native speakers: ', response['native-speakers']) - print('') + print('## Response Object ##') + print(json.dumps(response, indent=4)) + + print('') + print('## Language ##') + print('language: ', response['language']) + print('iso-639-1: ', response['iso-639-1']) + print('native speakers: ', response['native-speakers']) + print('') else: - print('Error in language detection call: ', response['statusInfo']) - + print('Error in language detection call: ', response['statusInfo']) print('') @@ -303,20 +313,18 @@ print('Processing url: ', demo_url) print('') -response = alchemyapi.title('url',demo_url) +response = alchemyapi.title('url', demo_url) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) - + print('## Response Object ##') + print(json.dumps(response, indent=4)) - print('') - print('## Title ##') - print('title: ', response['title'].encode('utf-8')) - print('') + print('') + print('## Title ##') + print('title: ', response['title'].encode('utf-8')) + print('') else: - print('Error in title extraction call: ', response['statusInfo']) - + print('Error in title extraction call: ', response['statusInfo']) print('') @@ -331,29 +339,27 @@ print('Processing text: ', demo_text) print('') -response = alchemyapi.relations('text',demo_text) +response = alchemyapi.relations('text', demo_text) if response['status'] == 'OK': - print('## Object ##') - print(json.dumps(response, indent=4)) - - - print('') - print('## Relations ##') - for relation in response['relations']: - if 'subject' in relation: - print('Subject: ', relation['subject']['text'].encode('utf-8')) - - if 'action' in relation: - print('Action: ', relation['action']['text'].encode('utf-8')) - - if 'object' in relation: - print('Object: ', relation['object']['text'].encode('utf-8')) - - print('') -else: - print('Error in relation extaction call: ', response['statusInfo']) + print('## Object ##') + print(json.dumps(response, indent=4)) + print('') + print('## Relations ##') + for relation in response['relations']: + if 'subject' in relation: + print('Subject: ', relation['subject']['text'].encode('utf-8')) + + if 'action' in relation: + print('Action: ', relation['action']['text'].encode('utf-8')) + + if 'object' in relation: + print('Object: ', relation['object']['text'].encode('utf-8')) + + print('') +else: + print('Error in relation extaction call: ', response['statusInfo']) print('') @@ -368,21 +374,19 @@ print('Processing text: ', demo_text) print('') -response = alchemyapi.category('text',demo_text) +response = alchemyapi.category('text', demo_text) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) - - - print('') - print('## Category ##') - print('text: ', response['category']) - print('score: ', response['score']) - print('') + print('## Response Object ##') + print(json.dumps(response, indent=4)) + + print('') + print('## Category ##') + print('text: ', response['category']) + print('score: ', response['score']) + print('') else: - print('Error in text categorization call: ', response['statusInfo']) - + print('Error in text categorization call: ', response['statusInfo']) print('') @@ -397,24 +401,23 @@ print('Processing url: ', demo_url) print('') -response = alchemyapi.feeds('url',demo_url) +response = alchemyapi.feeds('url', demo_url) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) + print('## Response Object ##') + print(json.dumps(response, indent=4)) - print('') - print('## Feeds ##') - for feed in response['feeds']: - print('feed: ', feed['feed']) + print('') + print('## Feeds ##') + for feed in response['feeds']: + print('feed: ', feed['feed']) else: - print('Error in feed detection call: ', response['statusInfo']) + print('Error in feed detection call: ', response['statusInfo']) print('') print('') - print('') print('') print('') @@ -427,21 +430,21 @@ print('Processing url: ', demo_url) print('') -response = alchemyapi.microformats('url',demo_url) +response = alchemyapi.microformats('url', demo_url) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) + print('## Response Object ##') + print(json.dumps(response, indent=4)) - print('') - print('## Microformats ##') - for microformat in response['microformats']: - print('Field: ', microformat['field'].encode('utf-8')) - print('Data: ', microformat['data']) - print('') + print('') + print('## Microformats ##') + for microformat in response['microformats']: + print('Field: ', microformat['field'].encode('utf-8')) + print('Data: ', microformat['data']) + print('') else: - print('Error in microformats parsing call: ', response['statusInfo']) + print('Error in microformats parsing call: ', response['statusInfo']) print('') print('') @@ -459,19 +462,19 @@ print('Processing url: ', demo_url) print('') -response = alchemyapi.imageExtraction('url',demo_url) +response = alchemyapi.imageExtraction('url', demo_url) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) + print('## Response Object ##') + print(json.dumps(response, indent=4)) - print('') - print('## Image ##') - print('Image: ', response['image']) - print('') + print('') + print('## Image ##') + print('Image: ', response['image']) + print('') else: - print('Error in image extraction call: ', response['statusInfo']) + print('Error in image extraction call: ', response['statusInfo']) print('') print('') @@ -489,19 +492,19 @@ print('Processing url: ', image_url) print('') -response = alchemyapi.imageTagging('url',image_url) +response = alchemyapi.imageTagging('url', image_url) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) - - print('') - print('## Keywords ##') - for keyword in response['imageKeywords']: - print(keyword['text'], ' : ', keyword['score']) - print('') + print('## Response Object ##') + print(json.dumps(response, indent=4)) + + print('') + print('## Keywords ##') + for keyword in response['imageKeywords']: + print(keyword['text'], ' : ', keyword['score']) + print('') else: - print('Error in image tagging call: ', response['statusInfo']) + print('Error in image tagging call: ', response['statusInfo']) print('') print('') @@ -519,20 +522,20 @@ print('Processing text: ', demo_text) print('') -response = alchemyapi.taxonomy('text',demo_text) +response = alchemyapi.taxonomy('text', demo_text) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) + print('## Response Object ##') + print(json.dumps(response, indent=4)) - print('') - print('## Categories ##') - for category in response['taxonomy']: - print(category['label'], ' : ', category['score']) - print('') + print('') + print('## Categories ##') + for category in response['taxonomy']: + print(category['label'], ' : ', category['score']) + print('') else: - print('Error in taxonomy call: ', response['statusInfo']) + print('Error in taxonomy call: ', response['statusInfo']) print('') print('') @@ -550,32 +553,31 @@ print('Processing text: ', demo_text) print('') -response = alchemyapi.combined('text',demo_text) +response = alchemyapi.combined('text', demo_text) if response['status'] == 'OK': - print('## Response Object ##') - print(json.dumps(response, indent=4)) - - print('') - - - print('## Keywords ##') - for keyword in response['keywords']: - print(keyword['text'], ' : ', keyword['relevance']) - print('') - - print('## Concepts ##') - for concept in response['concepts']: - print(concept['text'], ' : ', concept['relevance']) - print('') - - print('## Entities ##') - for entity in response['entities']: - print(entity['type'], ' : ', entity['text'], ', ', entity['relevance']) - print(' ') + print('## Response Object ##') + print(json.dumps(response, indent=4)) + + print('') + + print('## Keywords ##') + for keyword in response['keywords']: + print(keyword['text'], ' : ', keyword['relevance']) + print('') + + print('## Concepts ##') + for concept in response['concepts']: + print(concept['text'], ' : ', concept['relevance']) + print('') + + print('## Entities ##') + for entity in response['entities']: + print(entity['type'], ' : ', entity['text'], ', ', entity['relevance']) + print(' ') else: - print('Error in combined call: ', response['statusInfo']) + print('Error in combined call: ', response['statusInfo']) print('') print('') diff --git a/tests.py b/tests.py index 97e9422..e34882a 100644 --- a/tests.py +++ b/tests.py @@ -15,12 +15,11 @@ # limitations under the License. - from __future__ import print_function from alchemyapi import AlchemyAPI -test_text = 'Bob broke my heart, and then made up this silly sentence to test the PHP SDK' +test_text = 'Bob broke my heart, and then made up this silly sentence to test the PHP SDK' test_html = 'The best SDK Test | AlchemyAPI

Hello World!

My favorite language is PHP

' test_url = 'http://www.nytimes.com/2013/07/13/us/politics/a-day-of-friction-notable-even-for-a-fractious-congress.html?_r=0' test_jpg = 'pigeon.jpg' @@ -29,250 +28,237 @@ alchemyapi = AlchemyAPI() -#Entities +# Entities print('Checking entities . . . ') -response = alchemyapi.entities('text', test_text); +response = alchemyapi.entities('text', test_text) assert(response['status'] == 'OK') -response = alchemyapi.entities('html', test_html); +response = alchemyapi.entities('html', test_html) assert(response['status'] == 'OK') -response = alchemyapi.entities('url', test_url); +response = alchemyapi.entities('url', test_url) assert(response['status'] == 'OK') -response = alchemyapi.entities('random', test_url); -assert(response['status'] == 'ERROR') #invalid flavor +response = alchemyapi.entities('random', test_url) +assert(response['status'] == 'ERROR') # invalid flavor print('Entity tests complete!') print('') -#Keywords +# Keywords print('Checking keywords . . . ') -response = alchemyapi.keywords('text', test_text); +response = alchemyapi.keywords('text', test_text) assert(response['status'] == 'OK') -response = alchemyapi.keywords('html', test_html); +response = alchemyapi.keywords('html', test_html) assert(response['status'] == 'OK') -response = alchemyapi.keywords('url', test_url); +response = alchemyapi.keywords('url', test_url) assert(response['status'] == 'OK') -response = alchemyapi.keywords('random', test_url); -assert(response['status'] == 'ERROR') #invalid flavor +response = alchemyapi.keywords('random', test_url) +assert(response['status'] == 'ERROR') # invalid flavor print('Keyword tests complete!') print('') - - -#Concepts +# Concepts print('Checking concepts . . . ') -response = alchemyapi.concepts('text', test_text); +response = alchemyapi.concepts('text', test_text) assert(response['status'] == 'OK') -response = alchemyapi.concepts('html', test_html); +response = alchemyapi.concepts('html', test_html) assert(response['status'] == 'OK') -response = alchemyapi.concepts('url', test_url); +response = alchemyapi.concepts('url', test_url) assert(response['status'] == 'OK') -response = alchemyapi.concepts('random', test_url); -assert(response['status'] == 'ERROR') #invalid flavor +response = alchemyapi.concepts('random', test_url) +assert(response['status'] == 'ERROR') # invalid flavor print('Concept tests complete!') print('') - -#Sentiment +# Sentiment print('Checking sentiment . . . ') -response = alchemyapi.sentiment('text', test_text); +response = alchemyapi.sentiment('text', test_text) assert(response['status'] == 'OK') -response = alchemyapi.sentiment('html', test_html); +response = alchemyapi.sentiment('html', test_html) assert(response['status'] == 'OK') -response = alchemyapi.sentiment('url', test_url); +response = alchemyapi.sentiment('url', test_url) assert(response['status'] == 'OK') -response = alchemyapi.sentiment('random', test_url); -assert(response['status'] == 'ERROR') #invalid flavor +response = alchemyapi.sentiment('random', test_url) +assert(response['status'] == 'ERROR') # invalid flavor print('Sentiment tests complete!') print('') - -#Targeted Sentiment +# Targeted Sentiment print('Checking targeted sentiment . . . ') -response = alchemyapi.sentiment_targeted('text', test_text, 'heart'); +response = alchemyapi.sentiment_targeted('text', test_text, 'heart') assert(response['status'] == 'OK') -response = alchemyapi.sentiment_targeted('html', test_html, 'language'); +response = alchemyapi.sentiment_targeted('html', test_html, 'language') assert(response['status'] == 'OK') -response = alchemyapi.sentiment_targeted('url', test_url, 'Congress'); +response = alchemyapi.sentiment_targeted('url', test_url, 'Congress') assert(response['status'] == 'OK') -response = alchemyapi.sentiment_targeted('random', test_url, 'Congress'); -assert(response['status'] == 'ERROR') #invalid flavor -response = alchemyapi.sentiment_targeted('text', test_text, None); -assert(response['status'] == 'ERROR') #missing target +response = alchemyapi.sentiment_targeted('random', test_url, 'Congress') +assert(response['status'] == 'ERROR') # invalid flavor +response = alchemyapi.sentiment_targeted('text', test_text, None) +assert(response['status'] == 'ERROR') # missing target print('Targeted sentiment tests complete!') print('') - -#Text +# Text print('Checking text . . . ') -response = alchemyapi.text('text', test_text); -assert(response['status'] == 'ERROR') #only works for html and url content -response = alchemyapi.text('html', test_html); +response = alchemyapi.text('text', test_text) +assert(response['status'] == 'ERROR') # only works for html and url content +response = alchemyapi.text('html', test_html) assert(response['status'] == 'OK') -response = alchemyapi.text('url', test_url); +response = alchemyapi.text('url', test_url) assert(response['status'] == 'OK') print('Text tests complete!') print('') - -#Text Raw +# Text Raw print('Checking raw text . . . ') -response = alchemyapi.text_raw('text', test_text); -assert(response['status'] == 'ERROR') #only works for html and url content -response = alchemyapi.text_raw('html', test_html); +response = alchemyapi.text_raw('text', test_text) +assert(response['status'] == 'ERROR') # only works for html and url content +response = alchemyapi.text_raw('html', test_html) assert(response['status'] == 'OK') -response = alchemyapi.text_raw('url', test_url); +response = alchemyapi.text_raw('url', test_url) assert(response['status'] == 'OK') print('Raw text tests complete!') print('') - -#Author +# Author print('Checking author . . . ') -response = alchemyapi.author('text', test_text); -assert(response['status'] == 'ERROR') #only works for html and url content -response = alchemyapi.author('html', test_html); -assert(response['status'] == 'ERROR') #there's no author in the test HTML -response = alchemyapi.author('url', test_url); +response = alchemyapi.author('text', test_text) +assert(response['status'] == 'ERROR') # only works for html and url content +response = alchemyapi.author('html', test_html) +assert(response['status'] == 'ERROR') # there's no author in the test HTML +response = alchemyapi.author('url', test_url) assert(response['status'] == 'OK') print('Author tests complete!') print('') - -#Language +# Language print('Checking language . . . ') -response = alchemyapi.language('text', test_text); +response = alchemyapi.language('text', test_text) assert(response['status'] == 'OK') -response = alchemyapi.language('html', test_html); +response = alchemyapi.language('html', test_html) assert(response['status'] == 'OK') -response = alchemyapi.language('url', test_url); +response = alchemyapi.language('url', test_url) assert(response['status'] == 'OK') -response = alchemyapi.language('random', test_url); -assert(response['status'] == 'ERROR') #invalid flavor +response = alchemyapi.language('random', test_url) +assert(response['status'] == 'ERROR') # invalid flavor print('Language tests complete!') print('') - -#Title +# Title print('Checking title . . . ') -response = alchemyapi.title('text', test_text); -assert(response['status'] == 'ERROR') #only works for html and url content -response = alchemyapi.title('html', test_html); +response = alchemyapi.title('text', test_text) +assert(response['status'] == 'ERROR') # only works for html and url content +response = alchemyapi.title('html', test_html) assert(response['status'] == 'OK') -response = alchemyapi.title('url', test_url); +response = alchemyapi.title('url', test_url) assert(response['status'] == 'OK') print('Title tests complete!') print('') - -#Relations +# Relations print('Checking relations . . . ') -response = alchemyapi.relations('text', test_text); +response = alchemyapi.relations('text', test_text) assert(response['status'] == 'OK') -response = alchemyapi.relations('html', test_html); +response = alchemyapi.relations('html', test_html) assert(response['status'] == 'OK') -response = alchemyapi.relations('url', test_url); +response = alchemyapi.relations('url', test_url) assert(response['status'] == 'OK') -response = alchemyapi.relations('random', test_url); -assert(response['status'] == 'ERROR') #invalid flavor +response = alchemyapi.relations('random', test_url) +assert(response['status'] == 'ERROR') # invalid flavor print('Relation tests complete!') print('') - -#Category +# Category print('Checking category . . . ') -response = alchemyapi.category('text', test_text); +response = alchemyapi.category('text', test_text) assert(response['status'] == 'OK') -response = alchemyapi.category('html', test_html, {'url':'test'}); +response = alchemyapi.category('html', test_html, {'url': 'test'}) assert(response['status'] == 'OK') -response = alchemyapi.category('url', test_url); +response = alchemyapi.category('url', test_url) assert(response['status'] == 'OK') -response = alchemyapi.category('random', test_url); -assert(response['status'] == 'ERROR') #invalid flavor +response = alchemyapi.category('random', test_url) +assert(response['status'] == 'ERROR') # invalid flavor print('Category tests complete!') print('') - -#Feeds +# Feeds print('Checking feeds . . . ') -response = alchemyapi.feeds('text', test_text); -assert(response['status'] == 'ERROR') #only works for html and url content -response = alchemyapi.feeds('html', test_html, {'url':'test'}); +response = alchemyapi.feeds('text', test_text) +assert(response['status'] == 'ERROR') # only works for html and url content +response = alchemyapi.feeds('html', test_html, {'url': 'test'}) assert(response['status'] == 'OK') -response = alchemyapi.feeds('url', test_url); +response = alchemyapi.feeds('url', test_url) assert(response['status'] == 'OK') print('Feed tests complete!') print('') - -#Microformats +# Microformats print('Checking microformats . . . ') -response = alchemyapi.microformats('text', test_text); -assert(response['status'] == 'ERROR') #only works for html and url content -response = alchemyapi.microformats('html', test_html, {'url':'test'}); +response = alchemyapi.microformats('text', test_text) +assert(response['status'] == 'ERROR') # only works for html and url content +response = alchemyapi.microformats('html', test_html, {'url': 'test'}) assert(response['status'] == 'OK') -response = alchemyapi.microformats('url', test_url); +response = alchemyapi.microformats('url', test_url) assert(response['status'] == 'OK') print('Microformat tests complete!') print('') print('') -#imagetagging +# imagetagging print('Checking imagetagging . . . ') -response = alchemyapi.imageTagging('text', test_text); -assert(response['status'] == 'ERROR') -response = alchemyapi.imageTagging('html', test_html); +response = alchemyapi.imageTagging('text', test_text) assert(response['status'] == 'ERROR') -response = alchemyapi.imageTagging('url', test_url); +response = alchemyapi.imageTagging('html', test_html) +assert(response['status'] == 'ERROR') +response = alchemyapi.imageTagging('url', test_url) assert(response['status'] == 'OK') -response = alchemyapi.imageTagging('image', test_jpg); +response = alchemyapi.imageTagging('image', test_jpg) assert(response['status'] == 'OK') print('Image tagging tests complete!') print('') print('') -#combined +# combined print('Checking combined . . . ') -response = alchemyapi.combined('text', test_text); +response = alchemyapi.combined('text', test_text) assert(response['status'] == 'OK') -response = alchemyapi.combined('html', test_html); -assert(response['status'] == 'ERROR') -response = alchemyapi.combined('url', test_url); +response = alchemyapi.combined('html', test_html) +assert(response['status'] == 'ERROR') +response = alchemyapi.combined('url', test_url) assert(response['status'] == 'OK') print('Combined tests complete!') print('') print('') -#taxonomy +# taxonomy print('Checking taxonomy . . . ') -response = alchemyapi.taxonomy('text', test_text); +response = alchemyapi.taxonomy('text', test_text) assert(response['status'] == 'OK') -response = alchemyapi.taxonomy('html', test_html, {'url':'test'}); -assert(response['status'] == 'OK') -response = alchemyapi.taxonomy('url', test_url); +response = alchemyapi.taxonomy('html', test_html, {'url': 'test'}) +assert(response['status'] == 'OK') +response = alchemyapi.taxonomy('url', test_url) assert(response['status'] == 'OK') print('Taxonomy tests complete!') print('') print('') -#image +# image print('Checking image extraction . . . ') -response = alchemyapi.imageExtraction('text', test_text); +response = alchemyapi.imageExtraction('text', test_text) +assert(response['status'] == 'ERROR') +response = alchemyapi.imageExtraction('html', test_html) assert(response['status'] == 'ERROR') -response = alchemyapi.imageExtraction('html', test_html); -assert(response['status'] == 'ERROR') -response = alchemyapi.imageExtraction('url', test_url); +response = alchemyapi.imageExtraction('url', test_url) assert(response['status'] == 'OK') print('Image Extraction tests complete!') print('') @@ -280,6 +266,3 @@ print('**** All tests complete! ****') - - - From 8e8fe07cf5aa27ba201bb80892a76737f05b1e47 Mon Sep 17 00:00:00 2001 From: Bobby Larson Date: Thu, 2 Oct 2014 12:07:20 -0600 Subject: [PATCH 2/2] Added in the requirement information for the Requests library. --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 0609034..84254e2 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,12 @@ To use AlchemyAPI, you'll need to obtain an API key and attach that key to all r +## Requirements ## + +The Python SDK requires that you install the [Requests Python module](http://docs.python-requests.org/en/latest/user/install/#install). + + + ## Getting Started with the Python SDK ## To get started and run the example, simply: