Description
The PlotDevice Web library offers a collection of services to retrieve content from the
internet. You can use the library to query Yahoo! for links,
images, news and spelling suggestions, to read RSS and Atom newsfeeds, to retrieve articles
from Wikipedia, to collect quality images from morgueFile or Flickr, to
get color themes from kuler or Colr, to browse through HTML documents, to clean up HTML, to validate
URL’s, to create GIF images from math equations using mimeTeX, to get ironic word definitions from Urban Dictionary.
The PlotDevice Web library works with a caching mechanism that stores things you download from the web, so they can be retrieved faster the next time. Many of the services also work asynchronously. This means you can use the library in an animation that keeps on running while new content is downloaded in the background.
The library bundles Leonard Richardson’s Beautiful Soup to parse HTM, Mark Pilgrim’s
Universal Feed Parser for newsfeeds, a connection to
John Forkosh’s mathTeX server (thanks Cedric Foellmi), Leif K-Brooks entity replace algorithm,
simplejson, and patches for Debian from the
people at Indywiki.
Download
web.zip (390KB) Last updated for NodeBox 1.9.4.6 Licensed under GPL Author: Tom De Smedt |
Documentation
- How to get the library up and running
- Validating web content
- Working with URL’s
- Working with HTML
- Querying Yahoo! for links, images and news
- Improving Yahoo! results with a contextual search
- Using Yahoo! to suggest spelling corrections
- Using Yahoo! to sort associatively
- Querying Google
- Reading newsfeeds
- Retrieving articles from Wikipedia
- Some helper commands to draw Wikipedia content in PlotDevice
- Querying morgueFile for images
- Querying Flickr for images
- Querying kuler for color themes
- Querying Colr for color schemes
- Creating GIF images from math equations
- Word definitions from Urban Dictionary
- Working with asynchronous downloads
- Clearing the cache
- Reading JSON
How to get the library up and running
Put the web library folder in the same folder as your script so PlotDevice can find the
library.
You can also put it in ~/Library/Application Support/PlotDevice/.
web = ximport("web")
Outside of PlotDevice you can also just do import web.
Proxy servers
If you are behind a proxy server the library may not be able to connect to the internet.
In that case you need to inform the library with the set_proxy() command:
web.set_proxy("https://www.myproxyserver.com:80", type="https")
Validating web content
Web content is accessed with a URL, the address you use to connect to a place on the internet. The library has a number of commands to find out what type of content (e.g. web page, image, ...) is associated with a given URL.
The most basic command, is_url() checks whether a given string is a grammatically correct URL (e.g. http://nodebox.net but not htp://nodebox.net). It takes a wait parameter indicating the number of seconds after which the library should stop connecting to the internet and give up.
web.is_url(url, wait=10)
Even if a URL is valid, it might not refer to actual content on the internet. We can check if a URL exists with the not_found() command:
web.url.not_found(url, wait=10)
The following commands are useful to find out what content is associated with the URL. We can discern between HTML web pages which we can parse with page.parse(), newsfeeds which we can parse with newsfeed.parse(), images, audio and video etc. which we can download with url.retrieve().
web.url.is_webpage(url, wait=10)
web.url.is_stylesheet(url, wait=10)
web.url.is_plaintext(url, wait=10)
web.url.is_pdf(url, wait=10)
web.url.is_newsfeed(url, wait=10)
web.url.is_image(url, wait=10)
web.url.is_audio(url, wait=10)
web.url.is_video(url, wait=10)
web.url.is_archive(url, wait=10)
Working with URL’s
A URL is the address you use to connect to a page on the internet, for example: http://nodebox.net. The PlotDevice Web library can do three different things with a URL: download the content associated with it, parse it (find out which parts make up the URL) and construct it from scratch (a simple way to create a URL with HTTP GET or HTTP POST data).
web.download(url, wait=60, cache=None, type=".html")
web.save(url, path="", wait=60)
web.url.retrieve(url, wait=60, asynchronous=False, cache=None, type=".html")
web.url.parse(url)
web.url.create(url="", method="get")
The download() command returns the content associated with the given web address. The command has an optional parameter wait that determines how long to wait for a download. If the time is exceeded, the download is aborted.
The last two parameters can be used to cache downloaded content locally, so it doesn’t have to downloaded again in the future. The cache parameter is a string with the name of a subfolder in /cache where to store content. The type parameter is the file extension of the downloaded content.
The save() command stores the URL’s content at the given local path. If no path is given it will attempt to extract a filename from the URL and store that in the current working directory. The path to the saved file is returned.
The Web library also has easier ways to deal with specific web content like HTML (page.parse() command) or Wikipedia articles (wikipedia.search() command) for example.
The download() command is actually an alias of the url.retrieve() command.
This command has an additional asynchronous parameter useful to download stuff in the
background while an animation keeps on running. We’ll see about asynchronous downloads
later on. The url.retrieve() command returns an object with a data property
containing a string with the downloaded content. If you don’t need anything that complicated
just use the easy download() command:
# Download an image from the PlotDevice Gallery. url = "http://nodebox.net/code/data/media/twisted-final.jpg" img = web.download(url) # Display the image data in PlotDevice. image(None, 0, 0, data=img) # Write the image data to a file. file = open("twisted.jpg", "w") file.write(img) file.close()
The url.parse() command splits a given url into its components. The returned objects has the following properties:
- url.protocol: the type of internet service, usually http
- url.domain: the domain name, for example, nodebox.net
- url.username: a username for a secure connection
- url.password: a password for a secure connection
- url.port: the port number at the host
- url.path: the subdirectory at the server, for example /code/index.php/
- url.page: the name of the document, for example search
- url.anchor: named anchor on the page
- url.query: a dictionary of query string values, for example { ‘q’: ‘pixels’
}
- url.method: the query string method either ‘get’ or ‘post’
In the same way the url.create() command returns an object with these properties. This command is useful to, for example, construct URL’s with a POST query and pass that to url.retrieve() or page.parse().
For example. this script retrieves the first 10 forum pages from PlotDevice:
url = web.url.create("http://nodebox.net/code/index.php/Share") url.query["p"] = 1 for i in range(10): print web.url.retrieve(url).data url.query["p"] += 1
Working with HTML
The PlotDevice Web library uses Leonard Richardson’s Beautiful Soup to parse HTML content. This means you can search and loop through all the tags in the HTML. For example, you might want to download a HTML page from the internet, find all the links in it and then download all those links. Or find all the image tags in the source and then retrieve all those images with download().
The page.parse() command takes a URL as input and returns a Beautiful Soup object. The optional cached parameter determines if downloaded pages should be cached locally for faster retrieval.
web.page.parse(url, wait=10, cached=True)
You can get the meta information in the HTML header with the returned object’s title, description and keywords properties:
html = web.page.parse("http://nodebox.net") print html.description >>> PlotDevice is a Mac OS X application that lets you create 2D visuals >>> (static, animated or interactive) using Python programming code >>> and export them as a PDF or a QuickTime movie. PlotDevice is free >>> and well-documented. print html.keywords >>>[u'PlotDevice', u'Home']
You can easily get all the links in the HTML with the links() method. It takes an optional external parameter which when True, returns only links to other domains/websites.
html = web.page.parse("http://nodebox.net/code/index.php/About") print html.links() >>> [u'http://research.nodebox.net', >>> u'http://www.opensource.org/licenses/mit-license.php', >>> u'http://www.python.org/', u'http://bert.debruijn.be/kgp/', >>> u'http://diveintopython.org/xml_processing/', >>> u'http://processing.org', >>> u'http://www.freelists.org/archives/the_posthumans/', >>> u'http://research.nodebox.net' >>> ]
The find_all() method returns a list of specific tags. The find() method just returns the first tag:
html = web.page.parse("http://nodebox.net/") print html.find("title").string >>> PlotDevice | Home titles = html.find_all("h2") for title in titles: print title.string >>> News >>> Current projects >>> Gallery favorites content = html.find(id="content") print web.html.plain(content) >>> Welcome to PlotDevice PlotDevice is a Mac OS X application >>> that lets you create 2D visuals (static, animated or interactive) >>> using Python programming code and export them as a PDF or >>> a QuickTime movie. PlotDevice is free and well-documented. >>> Read more >>> >>> Download PlotDevice for Mac OS X (version 1.8.5) Universal Binary >>> >>> Latest updates: >>> >>> * Interactivity >>> * Stop running scripts by hitting command-dot. >>> ...
As you can see you can supply tag names or attribute-value pairs to the find methods.
The find() and find_all() methods return Tag objects that each have find() and find_all() too. Alternatively, you can also find tags more directly, for example: html.body.p returns a list of all p tags.
html = web.page.parse("http://nodebox.net/") list = html.find(id="content").find("ul") print web.html.plain(list) >>> * Interactivity >>> * Stop running scripts by hitting command-dot. >>> * Transparent PDFs with the background() command. >>> * Fast, integrated path mathematics . >>> * Store libaries centrally in the Application Support folder. # These statements retrieve exactly the same. list = html.body(id="content")[0].ul list = html.body.ul
If you need to retrieve tags by their CSS classname, use the find_class() method.
To get attributes from a tag, address it as a dictionary:
html = web.page.parse("http://nodebox.net/") html.body.a["href"] # the first link's href attribute >>> Home
The PlotDevice Web library has various commands to clean up HTML.
# Replaces HTML special characters by readable characters. web.html.replace_entities(unicode, placeholder=" ")
# Removes all tags from HTML except those in the exclude list. web.html.strip_tags(html, exclude=[], linebreaks=False, blocks="\n", breaks="\n", columns="\n")
web.html.strip_javascript(html)
web.html.strip_inline_css(html)
web.html.strip_comments(html)
web.html.strip_forms(html)
# If there are 10 consecutive spaces, 9 of them are removed. web.html.collapse_spaces(str)
# Allow only a maximum of max linebreaks to build up. web.html.collapse_linebreaks(str, max=2)
# Converts tabs to spaces, optionally leaving the left indentation unmodified. web.html.collapse_tabs(str, indent=False)
# Combines all of the above. web.html.plain(html)
Querying Yahoo! for links, images and news
Before you can use the Web library to query the Yahoo! search engine, you need to obtain a license key: http://developer.yahoo.com/search/
Click ‘get an application ID’. Fill out the form and you’ll end up with a long string
of numbers and characters which is your Yahoo! license key. It entitles you to 5000 queries a
day. Now register your license key in your PlotDevice script:
web.yahoo.license_key("myID") print web.yahoo.license_key() >>> myID
Note that you can query Yahoo! without setting a license key, in which case you are using a default key that you share with all the other PlotDevice users who work with the Web library.
Use the yahoo.search(), yahoo.search_images() and yahoo.search_news() commands to query Yahoo! for links to relevant webpages/images/news:
web.yahoo.search(q, start=1, count=10, context=None, cached=False)
web.yahoo.search_images(q, start=1, count=10, cached=False)
web.yahoo.search_news(q, start=1, count=10, cached=False)
The commands take a q query parameter, and optional start, count and cached parameters. The start parameter defines the first link to return, count defines the total amount of links to return. The cached parameter defines if Yahoo queries are cached locally (so they can be retrieved faster in the future).
results = web.yahoo.search("plotdevice", start=1, count=5, cached=False) for item in results: print item.title >>> PlotDevice | Home >>> PlotDevice | Features >>> visualcomplexity.com | PlotDevice >>> PlotDevice - Wikipedia, the free encyclopedia >>> Nodebox - SWiK
Each item in the list of results is a YahooResult object with the following properties:
- result.url: the URL of the linked page
- result.title: the title of the linked page
- result.description: a short description for the page
- result.type: the MIME-type of the linked page
- result.date: the modification date of the linked page
- result.width: for images, the width in pixels
- result.height: for images, the height in pixels
- result.source: for news items, the source of the article
- result.language: for news items, the language used
The list of results has a total property containing the total number of results Yahoo! has for your query:
print results.total >>> 37200
Improving Yahoo! results with a contextual search
Suppose you are querying Yahoo! for apple. Most likely Yahoo! will return links to pages relating to the Apple Computer company. But perhaps you wanted links to apples as in fruit. The yahoo.search() command has an optional context parameter which you can supply a description of what you mean exactly with apple:
ctx = ''' The apple tree was perhaps the earliest tree to be cultivated, and apples have remained an important food in all cooler climates. To a greater degree than other tree fruit, except possibly citrus, apples store for months while still retaining their nutritive value. We are not looking for a company named Apple. ''' results = web.yahoo.search("apple", count=5, context=ctx) print r.total for item in results: print item.title >>> Apple - Wikipedia, the free encyclopedia >>> Apple Core >>> Apple - Free Encyclopedia >>> Apple : Apple (fruit) >>> About the Apple -- Fruit
Using Yahoo! to suggest spelling corrections
To get spelling suggestions from Yahoo, use the yahoo.suggest_spelling() command. It returns a list of suggested spelling corrections:
corrections = web.yahoo.suggest_spelling ("amazoon", cached=False) print corrections >>> ['amazon']
Using Yahoo! to sort associatively
You can use Yahoo! to sort concepts according to association. Is sky more green, red or blue?
colors = ["green", "blue", "red"] sorted = web.yahoo.sort(colors, "sky", strict=False, cached=True) for word, weight in sorted: print word, weight >>> blue sky 0.396039408425 >>> red sky 0.33604773392 >>> green sky 0.267912857655
In this example, Yahoo! is queried for green sky, blue sky and red sky. The result is a sorted list of (query, weight) tuples. We learn that blue is the color best associated with sky.
The Prism algorithm roughly works in this way.
Querying Google
You can run Google queries in the same way as querying Yahoo!.
The library has the following commands available:
web.google.search(q, start=0, cached=False)
web.google.search_images(q, start=0, size="", cached=False)
web.google.search_news(q, start=0, cached=False)
web.google.search_blogs(q, start=0, cached=False)
web.google.sort(words, context="", strict=True, cached=False)
The search commands return a list of results. This list has an additional total property. Each item in the list is a GoogleResult object with the following properties:
- result.url: the URL of the linked page
- result.title: the title of the linked page
- result.description: a short description for the page
- result.date: for news and blogs search
- result.author: for news and blogs search.
- result.location: for news search.
Per search, a list of 8 items is returned from the given start item. Google will only ever return the first 32 results, so the maximum value for start is 24.
When searching for images, the results can be filtered for image size with the
optional size parameter.
Acceptable values are ‘small’, ‘medium’, ‘large’ and ‘wallpaper’.
Reading newsfeeds
The newsfeed.read() command returns information from RSS or Atom newsfeeds as a collection of news items with a title, link, description, and more.
web.newsfeed.parse(url, wait=10, cached=True)
The returned newsfeed object has the following properties:
- newsfeed.title: the title of the newsfeed
- newsfeed.description: a short description for the newsfeed
- newsfeed.link: a link to the homepage of the news channel
- newsfeed.date: a publication date of the news channel
- newsfeed.encoding: the text encoding used (usually Unicode)
- newsfeed.items: a list of news items
The items property is a list in which each item object has properties of its own:
- item.title: the title of the news item
- item.link: a link to the full article online
- item.description: a short description of the news item
- item.date: the publication date of the news item
- item.author: the author of the news item
newsfeed = web.newsfeed.parse"http://www.whitehouse.gov/rss/news.xml") print "Channel:", newsfeed.title print "Channel description:", newsfeed.description for item in newsfeed.items: print "Title:", item.title print "Link:", item.link print "Description", item.description print "Date:", item.date print "Author:", item.author
There are other properties as well, like item.date_parsed, item.author_detail and
item.author_detail.email. See the Universal Feed
Parser documentation for more information.
The address of some well-known newsfeeds can be found in the newsfeed.favorites dictionary or with the newsfeed.favorite_url() command:
print web.newsfeed.favorite_url("apple") >>> http://images.apple.com/main/rss/hotnews/hotnews.rss
Retrieving articles from Wikipedia
Wikipedia is a multilingual, web-based, free content encyclopedia project. Wikipedia is written collaboratively by volunteers; the vast majority of its articles can be edited by anyone with access to the Internet.
The wikipedia.search() command retrieves articles from Wikipedia. It parses an article corresponding to the given query into lists of related articles and paragraphs of plain text without any HTML or other markup in it:
web.wikipedia.search(q, language="en", light=False, wait=10, cached=True)
The command takes a q query parameter and, optionally, the language the article should be written in. When light is True, only a title, links to other articles, categories and disambiguation will be parsed from the article (it’s faster than a full parse).
Note that the q parameter is case-insenstive - this gives the best chance of
retrieving an article.
If you do want case-sensitivity use search(q, case_sensitive=True).
The return value is an article object with the following properties:
- article.title: the title of the article
- article.links: a list of titles of related articles
- article.categories: a list of categories this article belongs to
- article.disambiguation: a list of article titles describing other interpretations of the query
- article.paragraphs: a list of paragraph objects
(WikipediaParagraph)
- article .images: a list of image objects (WikipediaImage)
- article.tables: a list of table objects (WikipediaTable)
- article.references: a list of reference objects (WikipediaReference)
- article.translations: a dictionary of language keys linking to title
translations
- article.important: important phrases that appear in bold in the online
article
- article.markup: the source text of the article in MediaWiki markup
Article links
Each of the titles in the article.links list can be supplied to wikipedia.search() to get more information on that topic.
article = web.wikipedia.search("plotdevice") print article.title print article.links >>> PlotDevice >>> [u'2007', u'2D computer graphics', u'Adobe Photoshop', u'Animation', >>> u'CMYK', u'Computer animation', u'Core Image', u'DrawBot', >>> u'February 27', u'Graphic design', u'HSV color space', >>> u'MIT License', u'Mac OS X', u'OpenGL', u'Portable Document Format', >>> u'PostScript', u'Processing (programming language)', >>> u'Python (programming language)', u'QuickTime', u'RGB', u'SVG', >>> u'WordNet', u'alpha transparency', u'artificial intelligence', >>> u'collage', u'graphic design' >>> ]
Article paragraphs
Each paragraph object in article.paragraphs is a list of plain text blocks. Furthermore, a paragraph has a number of properties. This code snippet loops through all the paragraphs:
article = web.wikipedia.search("plotdevice") for paragraph in article.paragraphs: # A paragraph's depth determines # if it's a subparagraph or a top-level paragraph. if paragraph.depth <= 1: print "="*100 else: print "-"*100 print paragraph.title + "\n" # Each paragraph is a list of separate blocks of text: for textblock in paragraph: print textblock + "\n"
To display a paragraph with the text() command you can loop over all the textblocks individually:
fontsize(10) x, y, w = 20, 20, 300 for textblock in article.paragraphs[0]: text(textblock, x, y, width=w) y += textheight(textblock, width=w) + 10
Or simply use the Python str() command on the entire list:
text(str(article.paragraphs[0]), 20, 20, width=300)
A paragraph object has the following properties:
- paragraph.title: the title or heading of this paragraph
- paragraph.depth: the depth of the paragraph
- paragraph.parent: a WikipediaParagraph object containing this subparagraph
- paragraph.children: a list of sub-WikipediaParagraph objects
- paragraph.main: a list of article titles whose contents describe this paragraph in detail
- paragraph.related: more article titles that have related contents
- paragraph.tables: a list of WikipediaTable objects found in this
paragraph
Article images
Image objects in the article.images list have properties (like a description) that can help in discerning what is being displayed in the image:
article = web.wikipedia.search("computer") for img in article.images: print img.description >>> The NASA Columbia Supercomputer. >>> A computer in a wristwatch. >>> The Jacquard loom was one of the first programmable devices. >>> ...
An image object has the following properties:
- image.path: the image’s filename
- image.description: a description parsed from the source content
- image.links: a list of related article titles
- image properties: a list of properties parsed from the source (e.g. left,
thumb, ...)
Finally, here is a little web mash-up to draw article images in PlotDevice:
# 1) Get the image filename from the article. article = web.wikipedia.search("computer") img = article.images[0] # 2) Get the HTML for the Wikipedia page displaying the full-size image img = img.path.replace(" ", "_") html = web.page.parse("http://en.wikipedia.org/wiki/Image:"+img) # 3) Find the link in the HTML pointing to the image file. for a in html.find_all("a"): if a.has_key("href") and a["href"].endswith(img): img = a["href"] break # 4) Download the image link. # Pass the downloaded data to the image() command. img = web.download(img) image(None, 0, 0, data=img)
Article tables
Tables parsed from an article can be accessed from the article.tables list or from article.paragraph[i].tables. A table object is a list of rows. Each row is a list of cells:
article = web.wikipedia.search("computer") table = article.tables[0] print table.paragraph.title print table.title, "("+table.properties+")" for row in table: print "-"*50 print row.properties for cell in row: print cell, "("+cell.properties+")"
As you can see, tables, rows and cells all have properties. Tables also have a title property and a paragraph property linking to the paragraph object in which this table was found.
Article references
Text blocks in a Wikipedia paragraph can contain numerous references to websites, journal and footnotes. They are marked as a number between square brackets, e.g. [15].
For example:
>>> A key component common to all CPUs is the program counter, >>> a special memory cell (a register) that keeps track of which >>> location in memory the next instruction is to be read from. [11]
corresponds to article.references[10] - keeping in mind that list indices start from 0:
print article.references[10] >>> Instructions often occupy more than one memory address, >>> so the program counters usually increases by the number of >>> memory locations required to store one instruction
Each reference object in the article.references list has a number of properties. In the worst case all of the information is stored in reference.note, in the best case the reference has data for all of the folllowing properties:
- reference.title: a title of a publication
- reference.url: a link to a web page
- reference.author: the author of a publication
- reference.first: the author’s first name
- reference.last: the author’s last name
- reference.journal: the journal in which the article is published
- reference.publisher: the journal’s publisher
- reference.date: publication date
- reference.year: publication year
- reference.id: an ISBN book number
- reference.note: footnotes and descriptions
Article translations
Here’s an example script how to get the translated version of an article:
article = web.wikipedia.search("computer") language = "fr" if article.translations.has_key(language): translation = article.translations[language] article = web.wikipedia.search(translation, language) print article.title >>> Ordinateur
The dictionary of all languages used in Wikipedia:
print web.wikipedia.languages
Some helper commands to draw Wikipedia content in PlotDevice
A number of commands in the library can help you find out how to display content from Wikipedia in PlotDevice. There are commands to draw lists, math equations and tables.
# Returns True if a given text block str in a paragraph # is preformatted text, e.g. a programming code example. web.wikipedia.is_preformatted(str)
# Returns True if a text block in a paragraph is a (numbered) list. web.wikipedia.is_list(str)
# Returns True if a text block in a paragraph is a math equation. web.wikipedia.is_math(str)
# Draws a list text block at x, y coordinates in PlotDevice. web.wikipedia.draw_list(str, x, y, w, padding=5, callback=None)
# Use mimeTeX to draw an image of a math equation at x, y. web.wikipedia.draw_math(str, x, y, alpha=1.0)
# Draws WikipediaTable object in PlotDevice; works very poorly. web.wikipedia.draw_table(table, x, y, w, padding=5)
Querying morgueFile for images
morgueFile contains photographs freely contributed by many artists to be used in creative projects by visitors to the site.
The morguefile.search() command returns a list of images on morgueFile that correspond to a given query. It has an optional parameter max specifying the maximum number of images to return:
web.morguefile.search(q, max=100, wait-10, cached=True)
web.morguefile.search_by_author(q, max=100, wait=10, cached=True)
Each image object in the returned list has the following properties:
- img.id: the unique morgueFile ID for the image
- img.category: the category the image belongs to
- img.author: the name of the author
- img.name: the image’s name
- img.url: the URL of the image thumbnail
img.width: the image width in pixels - img.height: the image height in pixels
- img.date: the date the image was added to morgueFile
images = web.morguefile.search("leaf", max=10) for img in images: print img.name, img.views >>> IMG_1662_d.JPG >>> fedegrafo_100_0221.jpg >>> cha827.jpg >>> Filiford_P1010003.JPG >>> IMG_8336.jpg >>> CIMG0012_s.JPG >>> Target_spot_disease_on_maple.JPG >>> IMG_1664.JPG >>> bumpy_leaf.JPG >>> Aztec_Grass.JPG
Each image object in the list has a download() method that stores the image file locally in cache. It has an optional parameter size, which can be set to ‘small’ (image thumbnail) or ‘large’ (default):
img = images[0] img.download(size="large", wait=60) image(img.path, 0, 0, width=img.width, height=img.height) print img.author, img.path >>> Filiford cache/morguefile/240060eb1e1a0628ae32aff811b167ef.JPG
Querying Flickr for images
Flickr is an online photo management and sharing
application.
You can query it for images in the same way as querying morgueFile.
web.flickr.search(q, start=1, count=100, wait=10, cached=True)
web.flickr.recent(start=1, count=100, wait=10, cached=True)
The flickr.search() command has two optional parameters: sort and match. The sort order can be set either to ‘interest’, ‘relevance’ (default) or ‘date’. The match parameter can be either ‘all’ (image tags must include all of the search words) or ‘any’ (default).
Each image object in the returned list has a download() method like the morgueFile
interface. The download() method has an optional size parameter which can be
‘square’, ‘small’, ‘medium’, ‘large’ and ‘wallpaper’. This way you can specify the size of the
image to download.
Querying kuler for color themes
kuler is an Adobe web-application that allows users to construct and share color themes.
The kuler.search() command returns a list of color themes on kuler that correspong to a given query. It has an optional page parameter defining the starting page (each page has 30 themes).
web.kuler.search(q, page=0, wait=10, cached=True)
web.kuler.search_by_id(id, page=0, wait=10, cached=True)
web.kuler.search_by_popularity(page=0, wait=10, cached=True)
web.kuler.search_by_rating(page=0, wait=10, cached=True)
Each theme object in the returned list has the following properties:
- theme.id: the unique kuler id for the theme
- theme.author: the name of the author
- theme.label: the title of the theme
- theme.tags: a list of keywords for a theme found with kuler.search_by_id()
- theme.darkest: a tuple of (R, G, B) values for the darkest color in the theme
- theme.lightest: a tuple of (R, G, B) values the lightest color in the theme
You can loop through a theme object as a list. Each item in the theme is a tuple of (R, G, B) values, which you can supply to fill() or stroke() in PlotDevice.
themes = web.kuler.search("banana") for r, g, b in themes[0]: print r, g, b # The kuler.preview() command gives you an idea of the theme's colors. web.kuler.preview(themes[0])
Each theme also has a draw() method that displays the colors in the theme in PlotDevice:
themes = web.kuler.search("banana") themes[0].draw(50, 50, w=40, h=120)
Querying Colr for color themes
Colr is an online tool by Lloyd Dalton to let people
fiddle around with colors.
You can query it for color themes in the same way as querying kuler.
web.colr.search(q, page=0, wait=10, cached=True)
web.colr.search_by_id(id, page=0, wait=10, cached=True)
web.colr.latest(page=0, wait=10, cached=True)
web.colr.random(page=0, wait=10, cached=True)
You can manipulate each theme object in the returned list as with the kuler interface.
Creating PNG or GIF images from math equations
John Forkosh has a mathTeX server that creates PNG or GIF images from math equations.
web.mathtext.png(equation, dpi=120, color="")
web.mathtext.gif(equation, dpi=120, color="")
The optional dpi parameter sets the image resolution, while color can be the name of a primary color (e.g. blue, green, red, ...)
equation = r"E = hf = \frac{hc}{\lambda} \,\! " img = web.mathtex.gif(equation) image(img, 0, 0)
Word definitions from Urban Dictionary
Urban Dictionary is a slang dictionary with user-defined description for words. You can often get some humorous (or cruel and childish) results from it.
The urbandictionary.search() command returns a list of definitions for a given word.
web.urbandictionary.search(q, cached=True)
Each definition object in the returned list has the following properties:
- definition.description: a description of the given word
- definition.example: example usage of the word in a sentence
- definition.author: the author who came up with the definition
- definition.links: a list of words linked to the definition
- definition.url: the web page where the definition can be found
definitions = web.urbandictionary.search("life") print definitions[0].description >>> A sexually-transmitted, terminal disease.
Working with asynchronous downloads
Downloading content from the internet may take a moment to complete. When running an animation in PlotDevice, you don’t want it to halt while PlotDevice waits for the download to complete. The Web library offers you the capability to download asynchronously. NodeBox will then continue running with the download taking place in the background memory. Once it is done you can start manipulating the retrieved data.
The url.retrieve() command has some optional parameters to do asynchronous downloads:
web.url.retrieve(url, wait=60, asynchronous=False, cache=None, type=".html")
With asynchronous set to True, the download will occur in the background. The returned object has a done property which is True when downloading has terminated. The object’s data property then contains the source data.
You can also set a wait amount of seconds that is the maximum amount of time PlotDevice will connect to the internet. When the limit is exceeded and no data was fully recovered, the returned object will have an error property set. When something else went wrong error will be set as well by the way, usually with a URLTimeout, a HTTPError or a HTTP404NotFound exception.
data = web.url.retrieve("http://nodebox.net", asynchronous=True) import time while not data.done: time.sleep(0.1) print "downloading..." print "done!" >>> downloading... >>> downloading... >>> downloading... >>> downloading... >>> done!
Since all of the services in the Web library build upon url.retrieve(), you can also use the asynchronous parameter with page.parse(), yahoo.search(), newsfeed.parse(), wikipedia.search(), morguefile.search(), morguefile_image.download() and kuler.search().
An exception is the Urban Dictionary which uses SOAP instead of url.retrieve().
Here’s a quick mash-up of an interactive link browser. It starts out with some links from Yahoo! and when you click on a link, it displays the links in that web page, and so on.
from math import sin import web # Get links from Yahoo! links = web.yahoo.search("plotdevice") from_yahoo = True retrieving = None speed(20) def draw(): global links, from_yahoo, retrieving background(0.2, 0.2, 0.15) y = 100 fontsize(15) # Traverse the current list of links. for link in links: # Wave each line of text horizontally. x = 100 + sin(FRAME*y/5000.0)*50 # Yahoo!, our starting point, # has links in a slightly different format. if from_yahoo: link = link.url # A link looks grey by default... fill(0.8) # unless the mouse is hovering over it... if x < MOUSEX < x+textwidth(link) and \ y-fontsize() < MOUSEY < y: # in which case it is pink. fill(1, 0, 0.5) # When the mouse is pressed on a link # and we are not downloading anything, # start a download of the link in the background. if mousedown and retrieving == None: retrieving = web.page.parse(link, asynchronous=True) # Draw the link to the screen. text(link, x, y) y += fontsize() * 1.5 # If we are downloading something # and the download is ready, # parse that web page and get links from it. # Update the current list of links with the links on this page. if retrieving != None and retrieving.done: links = retrieving.links() from_yahoo = False # We are done downloading. retrieving = None # We are busy downloading. if retrieving != None and not retrieving.done: fill(1, 1, 0) text("please wait....", 10, 20)
Clearing the cache
Most of the content you retrieve with the Web library is cached for faster retrieval in the
future. At some point you may want to empty the cache (it can grow quite large). This is easy -
to erase the cache completely just do:
web.clear_cache()
To clear individual caches:
web.yahoo.clear_cache() web.wikipedia.clear_cache() web.morguefile.clear_cache() # etc... clear_cache() is available for each service in the library
Reading JSON
JSON (JavaScript Object Notation) is a lightweight data-interchange format. If you have some JSON data you need to parse into a Python dictionary you can use the bundled and super-easy library by Patrick D. Logan:
colr_data = web.json.read(colr_data) for theme in colr_data["schemes"]: theme_id = theme["id"]
The PlotDevice Web library addresses the following API’s:
- Yahoo!: http://developer.yahoo.com/search/
- Wikipedia: http://www.mediawiki.org/wiki/API
- morgueFile: http://www.morguefile.com/wiki/index.php/Morguefile_api
- Flickr: http://www.flickr.com/services/api/
- kuler: http://deliciouslymeta.com/kuler/k_docs.php
- Colr: http://www.colr.org/api.html
- mimeTeX: http://www.forkosh.com/mimetex.html
- Urban Dictionary: http://www.urbandictionary.com/api.php