<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>a work on process &#187; hpricot</title>
	<atom:link href="http://jystewart.net/process/tag/hpricot/feed/" rel="self" type="application/rss+xml" />
	<link>http://jystewart.net/process</link>
	<description>notes from another web developer</description>
	<lastBuildDate>Tue, 27 Jul 2010 09:53:43 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Tracking Heathrow with twitter</title>
		<link>http://jystewart.net/process/2009/01/tracking-heathrow-with-twitter/</link>
		<comments>http://jystewart.net/process/2009/01/tracking-heathrow-with-twitter/#comments</comments>
		<pubDate>Thu, 29 Jan 2009 11:32:52 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[airport]]></category>
		<category><![CDATA[bot]]></category>
		<category><![CDATA[datamapper]]></category>
		<category><![CDATA[environment]]></category>
		<category><![CDATA[flights]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[heathrow]]></category>
		<category><![CDATA[heathrowtower]]></category>
		<category><![CDATA[hpricot]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[screen scraping]]></category>
		<category><![CDATA[sqlite]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/?p=552</guid>
		<description><![CDATA[
A few months back&#8212;while we were discussing the number of talking objects appearing on twitter&#8212;Jenny pointed out to me that all Heathrow airport arrivals and departures data is online. That set my mind racing, as if you know all the flights leaving that currently controversial airport, there are all manner of things you could begin <a href="http://jystewart.net/process/2009/01/tracking-heathrow-with-twitter/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://twitter.com/heathrowtower/status/1158181826"><img src="http://jystewart.net/process/wp-content/uploads/2009/01/picture-2-300x48.png" alt="It&#039;s 11.23 on Thursday" title="It&#039;s 11.23 on Thursday" width="300" height="48" class="aligncenter size-medium wp-image-551" /></a></p>
<p>A few months back&#8212;while we were discussing the number of <a href="http://infovore.org/archives/2008/02/28/making-bridges-talk/" title="Infovore &raquo; Making bridges talk">talking objects</a> appearing on twitter&#8212;<a href="http://www.jenny-bee.net/" title="jennybee.net">Jenny</a> pointed out to me that all Heathrow airport arrivals and departures data is online. That set my mind racing, as if you know all the flights leaving that currently controversial airport, there are all manner of things you could begin to do. Working out miles travelled and <a href="http://www.amee.com/" title="AMEE - The world&#8217;s energy meter   &raquo; (home)">carbon emitted</a>, spotting delays, and so on. But at the time it all came down to a quick note in <a href="http://culturedcode.com/things/" title="Things - task management on the Mac">Things</a> to some day set aside time to explore.</p>
<p>That day arrived this week. The data turned out to be pretty simple to scrape, with a quick wrapper around <a href="http://wiki.github.com/why/hpricot" title="Home - hpricot - GitHub">hpricot</a>, and to throw into an SQLite database using <a href="http://datamapper.org/doku.php" title="start    [DataMapper]">datamapper</a> to give me a little abstraction and a place to throw a variety of methods to make my code simpler. And then it was a small matter of employing <a href="http://twitter.rubyforge.org/">John Nunemaker&#8217;s twitter gem</a> to set up regular tweets letting followers in on how many flights in and out of Heathrow there have been lately.</p>
<p>The result is a rather pleasing hourly summary, that adds a little rhythm and background awareness into my day. You can follow it at <a href="http://twitter.com/heathrowtower">http://twitter.com/heathrowtower</a>.</p>
<p>Perhaps the biggest frustration with the data is that all destinations/origins are given as city names. Given that city names are hardly unique, and even if they were a given city may have several airports connecting with Heathrow, that makes it a bit trickier to do some of the more sophisticated calculations. My hope is that the flight codes (which are given) can soon be transformed into a list of airport codes, which can then open up a route to more useful and interesting data. (if anyone knows of an existing database that does that mapping, please let me know!)</p>
<p>I&#8217;m looking forward to that, but I&#8217;m also anticipating the ambient awareness that having the bot running will create. Will the hourly ritual of seeing a sentence or two about Heathrow activity reveal any patterns? If they do, maybe I&#8217;ll update the code to make more of those. We&#8217;ll see.</p>
<p>For now, please do <a href="http://twitter.com/heathrowtower" title="Twitter / heathrowtower">follow the tower on twitter</a>, tell people about it, send it messages if you spot anything interesting, and feel free to <a href="http://github.com/jystewart/heathrow/tree/master" title="jystewart's heathrow at master - GitHub">take a look at the code over on github</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2009/01/tracking-heathrow-with-twitter/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Is it time to upgrade drupal yet?</title>
		<link>http://jystewart.net/process/2008/03/is-it-time-to-upgrade-drupal-yet/</link>
		<comments>http://jystewart.net/process/2008/03/is-it-time-to-upgrade-drupal-yet/#comments</comments>
		<pubDate>Thu, 27 Mar 2008 11:52:45 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Notes]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[hpricot]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scraper]]></category>
		<category><![CDATA[upgrades]]></category>
		<category><![CDATA[yaml]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/2008/03/is-it-time-to-upgrade-drupal-yet/</guid>
		<description><![CDATA[Working with a number of non-profits I frequently find myself tasked with extending or upgrading drupal. Each new version of drupal has been a significant step forward and I&#8217;m usually keen to get up to date but there&#8217;s the small matter of the suite of modules most sites use that need to catch up with <a href="http://jystewart.net/process/2008/03/is-it-time-to-upgrade-drupal-yet/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>Working with a number of non-profits I frequently find myself tasked with extending or upgrading drupal. Each new version of drupal has been a significant step forward and I&#8217;m usually keen to get up to date but there&#8217;s the small matter of the suite of modules most sites use that need to catch up with changing APIs. With the release of Drupal 6 a few weeks back I found myself wanting a tool that would help me check if my chosen modules were ready for the upgrade yet.</p>
<p>The quick solution I came up was a screen-scraper that will take a YAML file listing the relevant modules and their URLs and check to see if a Drupal 6 version has been released as yet. I wrote it in ruby, because after all that PHP work it&#8217;s nice to slip back into a language that feels so comfortable. (and hpricot is delightful for quick scraping solutions).</p>
<p>In case it&#8217;s helpful for anyone I&#8217;ve popped <a href="http://pastie.caboo.se/171472">the ruby code</a> and <a href="http://pastie.caboo.se/171473">a sample yaml file</a> up as pasties. Currently it&#8217;s invoked from the command line (providing you have ruby and hpricot set up) with:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>drupal-modules.rb my-file.yaml</pre></div></div>

<p>A couple of nice enhancements would be to either grab the list of modules from an existing drupal database, or to set this up as a little web service where people input the modules they use and can check a web page or receive an email when there&#8217;s a status update. It could even lead into some discussion of where certain older modules should be considered redundant and/or replaced with newer options. Time&#8217;s not likely to let me build that, but I&#8217;d love to hear if someone else does.</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2008/03/is-it-time-to-upgrade-drupal-yet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A little scripting to help with HTML email &#8211; bringing styles inline</title>
		<link>http://jystewart.net/process/2007/12/a-little-scripting-to-help-with-html-email-bringing-styles-inline/</link>
		<comments>http://jystewart.net/process/2007/12/a-little-scripting-to-help-with-html-email-bringing-styles-inline/#comments</comments>
		<pubDate>Tue, 04 Dec 2007 20:22:15 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[hpricot]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[htmlemail]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/2007/12/a-little-scripting-to-help-with-html-email-bringing-styles-inline/</guid>
		<description><![CDATA[As anyone keeping an eye on my deli.cio.us feed may have noticed, quite a few links have appeared to information about the preparation of HTML email. It&#8217;s a nasty business, as a quick glance at the website of the email standards project will tell you. But sadly, nasty as it may be, sometimes it has <a href="http://jystewart.net/process/2007/12/a-little-scripting-to-help-with-html-email-bringing-styles-inline/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>As anyone keeping an eye on <a href="http://del.icio.us/jystewart" title="jystewart's bookmarks on del.icio.us">my deli.cio.us feed</a> may have noticed, quite a few links have appeared to information about the preparation of HTML email. It&#8217;s a nasty business, as a quick glance at the website of <a href="http://www.email-standards.org/" title="Home | Email Standards Project">the email standards project</a> will tell you. But sadly, nasty as it may be, sometimes it has to be done.</p>
<p>Even if the email I send out is going to have CSS scattered inline, for building the templates I&#8217;d much rather be able to focus on writing the structure of the document and leave worrying about my CSS for another time, and another file. That wouldn&#8217;t get me around the nastiness of having to use tables for anything but the simplest of layouts, but it still feels right to keep the separation for as long as possible.</p>
<p>I had a quick look for a tool that would take a stylesheet and an HTML document, and embed the rules online, but didn&#8217;t find one. So I turned to ruby. In theory it should be very easy to build something like this, because of <a href="http://code.whytheluckystiff.net/hpricot/" title="Hpricot, a fast and delightful HTML parser">hpricot</a>&#8217;s support for CSS selectors. If we had the CSS stored in a hash all it would take would be something like:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'hpricot'</span>
doc = Hpricot<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'my_page.html'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
css_as_hash.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>selector, rule<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#006600; font-weight:bold;">&#40;</span>doc<span style="color:#006600; font-weight:bold;">/</span>selector<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">set</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'style'</span>, rule<span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">puts</span> doc</pre></div></div>

<p>Obviously that wouldn&#8217;t play nicely if there were already any styles inline, but for the purposes of this project I assumed there wouldn&#8217;t be.</p>
<p>I had a quick look at the <a href="http://code.dunae.ca/css_parser/" title="Ruby CSS Parser">cssparser rubygem</a> but found that the sample code threw &#8216;method not found&#8217; errors so I decided to quickly roll my own class that would take a path to a CSS file, and convert it to a hash. All it took was a few minutes&#8217; work and the result was:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># This class takes a CSS file and provides a method to</span>
<span style="color:#008000; font-style:italic;"># parse it into a hash. Usage is:</span>
<span style="color:#008000; font-style:italic;"># </span>
<span style="color:#008000; font-style:italic;"># parser = SimpleCSSParser.new('/path/to/myfile.css')</span>
<span style="color:#008000; font-style:italic;"># hash_of_rules = parser.to_hash</span>
<span style="color:#008000; font-style:italic;">#</span>
<span style="color:#008000; font-style:italic;"># For more advanced CSS handling check out the cssparser gem</span>
<span style="color:#008000; font-style:italic;"># http://code.dunae.ca/css_parser/</span>
<span style="color:#9966CC; font-weight:bold;">class</span> SimpleCSSParser
&nbsp;
  <span style="color:#008000; font-style:italic;"># Receive and open the CSS file, storing its contents</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>path_to_file<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@css</span> = <span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>path_to_file<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">read</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># Convert the CSS into a hash, where the keys are the selectors</span>
  <span style="color:#008000; font-style:italic;"># and the values are the rules</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> to_hash
    <span style="color:#0066ff; font-weight:bold;">@to_hash</span> <span style="color:#006600; font-weight:bold;">||</span>= separate_rules.<span style="color:#9900CC;">inject</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>collection, rule<span style="color:#006600; font-weight:bold;">|</span>
      identifiers, rule = prepare_selectors_and_rule<span style="color:#006600; font-weight:bold;">&#40;</span>rule<span style="color:#006600; font-weight:bold;">&#41;</span>
      identifiers.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>identifier<span style="color:#006600; font-weight:bold;">|</span>
        collection<span style="color:#006600; font-weight:bold;">&#91;</span>identifier<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span>= <span style="color:#996600;">''</span>
        collection<span style="color:#006600; font-weight:bold;">&#91;</span>identifier<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">+</span>= rule
      <span style="color:#9966CC; font-weight:bold;">end</span>
      collection
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  private
    <span style="color:#9966CC; font-weight:bold;">def</span> separate_rules
      <span style="color:#0066ff; font-weight:bold;">@css</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'}'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># Strip comments and extraneous white space from our CSS rules</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> clean_up_rule<span style="color:#006600; font-weight:bold;">&#40;</span>css_rule<span style="color:#006600; font-weight:bold;">&#41;</span>
      css_rule = css_rule.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>\<span style="color:#006600; font-weight:bold;">/</span>\<span style="color:#006600; font-weight:bold;">*</span>.<span style="color:#006600; font-weight:bold;">+</span>?\<span style="color:#006600; font-weight:bold;">*</span>\<span style="color:#006600; font-weight:bold;">//</span>, <span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      css_rule.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>\n<span style="color:#006600; font-weight:bold;">|</span>\s<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006666;">2</span>,<span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">/</span>, <span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># Break apart our selector(s) and rule. We return an array</span>
    <span style="color:#008000; font-style:italic;"># of selectors to allow for situations where multiple selectors</span>
    <span style="color:#008000; font-style:italic;"># are specified (comma separated) for a single rule</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> prepare_selectors_and_rule<span style="color:#006600; font-weight:bold;">&#40;</span>rule<span style="color:#006600; font-weight:bold;">&#41;</span>
      parts = rule.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'{'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      selectors = parts<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">','</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">map</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:strip<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> selectors, clean_up_rule<span style="color:#006600; font-weight:bold;">&#40;</span>parts<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>With that in place, I can now call:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'hpricot'</span>
&nbsp;
doc = Hpricot<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'my_file.html'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
parser = SimpleCSSParser.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'my_file.css'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
parser.<span style="color:#9900CC;">to_hash</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>selector, rule<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#006600; font-weight:bold;">&#40;</span>doc<span style="color:#006600; font-weight:bold;">/</span>selector<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">set</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'style'</span>, rule<span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">puts</span> doc</pre></div></div>

<p>and have the result I wanted all along. It&#8217;s rather brittle because of the way it splits the rules up, and it won&#8217;t pull in @include&#8217;d files, handle multiple CSS files, or do anything to honour the proper inheritance rules, but for my purposes that&#8217;s okay. I bundled it all up in a file that can be called from the command line. You can <a href="http://pastie.caboo.se/124725" title="#124725 - Pastie">find that in this pastie</a>.</p>
<p>A nice (and really quite simple) addition would be to take Campaign Monitor&#8217;s <a href="http://www.campaignmonitor.com/blog/archives/2007/04/a_guide_to_css_support_in_emai_2.html" title="A Guide to CSS Support in Email: 2007 Edition - Campaign Monitor Blog">Guide to CSS Support in Email</a>, parse it and spit out warnings about which email clients will have issues with which CSS rules. If I get round to implementing that I&#8217;ll blog about it here. If you get there before me, do post a comment and let me know.</p>
<p><strong>UPDATE (5th Dec &#8216;07:</strong> I&#8217;ve posted <a href="/process/2007/12/exploring-ruby-css-parsers-tamtam-and-csspool/">a follow-up looking at some other Ruby CSS parsers</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2007/12/a-little-scripting-to-help-with-html-email-bringing-styles-inline/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Quick and Easy Feeds with Camping</title>
		<link>http://jystewart.net/process/2007/02/quick-and-easy-feeds-with-camping/</link>
		<comments>http://jystewart.net/process/2007/02/quick-and-easy-feeds-with-camping/#comments</comments>
		<pubDate>Tue, 27 Feb 2007 00:34:42 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Notes]]></category>
		<category><![CDATA[Atom]]></category>
		<category><![CDATA[Camping]]></category>
		<category><![CDATA[hpricot]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[Scraping]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/archives/2007/02/quick-and-easy-feeds-with-camping/</guid>
		<description><![CDATA[Rails is great for many things, but for very small apps, it can definitely be overkill. That&#8217;s where why the lucky stiff&#8217;s Camping micro-framework comes in. Where rails gets you started with a clearly defined structure and generally presumes you&#8217;re going to want to use a database, Camping makes no such assumptions and just provides <a href="http://jystewart.net/process/2007/02/quick-and-easy-feeds-with-camping/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>Rails is great for many things, but for very small apps, it can definitely be overkill. That&#8217;s where why the lucky stiff&#8217;s <a href="http://code.whytheluckystiff.net/camping/">Camping</a> micro-framework comes in. Where rails gets you started with a clearly defined structure and generally presumes you&#8217;re going to want to use a database, Camping makes no such assumptions and just provides a few nice hooks for micro apps.</p>
<p>I got started using Camping a couple of months ago. With a lot of travel coming up, I&#8217;m eager to keep up to date with special deals on flights and frequent flyer miles, and stumbled across <a href="http://www.milemaven.com">milemaven.com</a> which seemed a great source of that information. But it doesn&#8217;t provide feeds and I have no desire to visit the site every day, so I decided to dust off hpricot and combine it with Camping to scrape the site and deliver the contents to my news reader.</p>
<p>If I wanted to be strict about MVC, I&#8217;d probably do the actual scraping in the model, since for this app that&#8217;s the data store/source. But in the interests of simplicity I did the parsing in the controller, and even so my entire controller comes out at only 29 lines. A version with a few extra comments looks like:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> <span style="color:#6666ff; font-weight:bold;">Milemaven::Controllers</span>
  <span style="color:#9966CC; font-weight:bold;">class</span> Index <span style="color:#006600; font-weight:bold;">&lt;</span> R <span style="color:#996600;">'/(<span style="color:#000099;">\d</span>*)'</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> get code
      <span style="color:#008000; font-style:italic;"># Default to United Airlines</span>
      code = <span style="color:#006666;">109</span> <span style="color:#9966CC; font-weight:bold;">if</span> code.<span style="color:#9900CC;">blank</span>?
      <span style="color:#0066ff; font-weight:bold;">@url</span> = <span style="color:#996600;">&quot;http://www.milemaven.com/offers/program/fly/#{code}/&quot;</span>
	 content = <span style="color:#996600;">''</span>
&nbsp;
	 <span style="color:#008000; font-style:italic;"># I could actually make this more compact by just passing having</span>
	 <span style="color:#008000; font-style:italic;"># hpricot get the URL, but I want to capture the last_modified time and</span>
	 <span style="color:#008000; font-style:italic;"># the charset to use in my feed</span>
      <span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>@url, <span style="color:#996600;">'User-Agent'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Camping Milemaven Atom Feed Scraper'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span>
        f.<span style="color:#9900CC;">each_line</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>line<span style="color:#006600; font-weight:bold;">|</span> content <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006600; font-weight:bold;">&lt;</span> line <span style="color:#006600; font-weight:bold;">&#125;</span>
        <span style="color:#0066ff; font-weight:bold;">@charset</span> = f.<span style="color:#9900CC;">charset</span>
        <span style="color:#0066ff; font-weight:bold;">@updated</span> = f.<span style="color:#9900CC;">last_modified</span> <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      doc = Hpricot<span style="color:#006600; font-weight:bold;">&#40;</span>content<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
      rows = doc.<span style="color:#9900CC;">search</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;table.listData tr&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0066ff; font-weight:bold;">@title</span> = doc.<span style="color:#9900CC;">at</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'td.content h3'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">children</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_s</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># This first couple of rows are headers, so skip them</span>
      <span style="color:#0066ff; font-weight:bold;">@deals</span> = rows<span style="color:#006600; font-weight:bold;">&#91;</span>2..<span style="color:#9900CC;">rows</span>.<span style="color:#9900CC;">size</span><span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">collect</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>row<span style="color:#006600; font-weight:bold;">|</span>
        title = row.<span style="color:#9900CC;">search</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;td&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'title'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
        url = row.<span style="color:#9900CC;">search</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'td'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">children</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'href'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
        <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> title, <span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> url  <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> title.<span style="color:#0000FF; font-weight:bold;">nil</span>? <span style="color:#9966CC; font-weight:bold;">or</span> url.<span style="color:#0000FF; font-weight:bold;">nil</span>?
      <span style="color:#9966CC; font-weight:bold;">end</span>.<span style="color:#9900CC;">compact</span>
&nbsp;
      render <span style="color:#ff3333; font-weight:bold;">:index</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>And then the view is a quick wrapper around Builder to generate an atom feed. The skeleton looks like:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> <span style="color:#6666ff; font-weight:bold;">Milemaven::Controllers</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> index
    <span style="color:#0066ff; font-weight:bold;">@headers</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'Content-Type'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;application/atom+xml; charset=#{@charset}&quot;</span>
    xml = <span style="color:#6666ff; font-weight:bold;">Builder::XmlMarkup</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:target</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    xml.<span style="color:#9900CC;">instruct</span>!<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:xml</span>, <span style="color:#ff3333; font-weight:bold;">:encoding</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@charset</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># Generate feed</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The main limitation of the feeds generated this way is that it&#8217;s very hard to get real published/updated dates for the entries, particularly as the server doesn&#8217;t always return to the timestamp for the pages correctly.</p>
<p>I&#8217;ve actually been playing with making this all a bit more re-usable by setting up a DSL to lay out the scraping rules, meaning that both controller and view become usable for most pages. But it needs a bit more work, so I&#8217;ll save it for another (potential) post.</p>
<p><strong>UPDATE (Mar 28th)</strong>: Boaz Shmueli from Milemaven contacted me to let me know there are some feeds available from that site, such as <a href="http://www.milemaven.com/rss/route/IAD/TPE/" type="application/rss+xml">this one for the route from IAD to TPE</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2007/02/quick-and-easy-feeds-with-camping/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Corrected bus routes on Rails</title>
		<link>http://jystewart.net/process/2006/09/corrected-bus-routes-on-rails/</link>
		<comments>http://jystewart.net/process/2006/09/corrected-bus-routes-on-rails/#comments</comments>
		<pubDate>Tue, 26 Sep 2006 13:08:03 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Commentary]]></category>
		<category><![CDATA[bus routes]]></category>
		<category><![CDATA[hpricot]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[screen scraping]]></category>
		<category><![CDATA[the rapid]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/archives/2006/09/corrected-bus-routes-on-rails/</guid>
		<description><![CDATA[In the process of building my bus route app, I realised that half the data for bus stops is missing. While the site&#8217;s developers have done a good job of providing clear data on half the stops, if you want to see stops going in the other direction, you have to use a drop-down box <a href="http://jystewart.net/process/2006/09/corrected-bus-routes-on-rails/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>In the process of building my bus route app, I realised that half the data for bus stops is missing. While the site&#8217;s developers have done a good job of providing clear data on half the stops, if you want to see stops going in the other direction, you have to use a drop-down box that triggers an AJAX request and repopulates the table.</p>
<p>A little digging shows that the call is to:</p>
<p>http://www.ridetherapid.org/includes/ajax_return.php?mode=routestops&#038;direction={direction}>&#038;routeID={routeid}</p>
<p>which returns an HTML table with the relevant stop data. So in a sense, there are permalinks for each set of stops, but it&#8217;d be nice if they were more clearly advertised, particularly since the site as is won&#8217;t work for those without javascript switched on.</p>
<p>The other gotcha is that it seems the internal IDs for some routes don&#8217;t match their route numbers. If you try and retrieve the westbound stops for Route #14 the call is actually to:</p>
<p><a href="http://www.ridetherapid.org/includes/ajax_return.php?mode=routestops&#038;direction=W&#038;routeID=13">http://www.ridetherapid.org/includes/ajax_return.php?mode=routestops&#038;direction=W&#038;routeID=13</a></p>
<p>and when you make requests for route 13, the routeID passed is 14. The same disparity continues, suggesting that they&#8217;ve (sensibly) added primary keys to their database other than the route number. It turns out that ID is embedded in the markup within a comment showing the direction and the ID. For Route #50 that is:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&amp;lt;div id=&quot;stopListWrapper&quot;&gt;
&amp;lt;!-- E -&gt; 19 --&gt;
&amp;lt;div id=&quot;stopList&quot;&gt;
...
&amp;lt;/div&gt;
&amp;lt;/div&gt;</pre></div></div>

<p>Since the document is already being parsed using <a href="http://code.whytheluckystiff.net/hpricot/">hpricot</a>, we can get that with:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">internal_route_id = doc.<span style="color:#9900CC;">at</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;div#stopListWrapper&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">children</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_s</span>.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>\<span style="color:#006600; font-weight:bold;">-</span>\<span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006600; font-weight:bold;">&#40;</span>\d<span style="color:#006600; font-weight:bold;">+</span><span style="color:#006600; font-weight:bold;">&#41;</span> \<span style="color:#006600; font-weight:bold;">-</span>\<span style="color:#006600; font-weight:bold;">-</span>\<span style="color:#006600; font-weight:bold;">&gt;/</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span></pre></div></div>

<p>(get the div, note that the comment is the second child, and get the data with a regular expression)</p>
<p>I&#8217;ve updated my scraper and the service to grab data based on the correct IDs. The HTML views will follow suit shortly.</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2006/09/corrected-bus-routes-on-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scraping Grand Rapids bus routes</title>
		<link>http://jystewart.net/process/2006/09/scraping-grand-rapids-bus-routes/</link>
		<comments>http://jystewart.net/process/2006/09/scraping-grand-rapids-bus-routes/#comments</comments>
		<pubDate>Mon, 25 Sep 2006 11:49:11 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Commentary]]></category>
		<category><![CDATA[bus routes]]></category>
		<category><![CDATA[Grand Rapids]]></category>
		<category><![CDATA[hpricot]]></category>
		<category><![CDATA[open data]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[screen scraping]]></category>
		<category><![CDATA[the rapid]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/archives/2006/09/scraping-grand-rapids-bus-routes/</guid>
		<description><![CDATA[The Rapid, the bus service for Grand Rapids and surrounding areas, recently redesigned their website. The redesign was long overdue and the result certainly looks a lot cleaner, if still far from inspiring. They&#8217;ve added a flash-based map showing their routes (though it could do with being a little larger on the page) and added <a href="http://jystewart.net/process/2006/09/scraping-grand-rapids-bus-routes/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>The Rapid, the bus service for Grand Rapids and surrounding areas, recently redesigned their website. The redesign was long overdue and the result certainly looks a lot cleaner, if still far from inspiring. They&#8217;ve added <a href="http://www.ridetherapid.org/ride/routes/">a flash-based map</a> showing their routes (though it could do with being a little larger on the page) and added PDF maps of each route (eg. <a href="http://www.ridetherapid.org/fileDisplay/index.php?routeFile=1158161765_route6.pdf)">this one for Route 6</a>). Unfortunately as yet there&#8217;s no tool for working out routes, but that&#8217;s not a big surprise.</p>
<p>My favourite features, however, are not any of those mentioned above but the fact that each route now has a clean URL (eg. <a href="http://www.ridetherapid.org/ride/routes/6/">http://www.ridetherapid.org/ride/routes/6/</a>) and a link to google maps for each stop, thereby exposing the coordinates of all the stops. With those two components in place, it becomes very easy to pull out the route data and begin to apply it to other uses. A ruby script (using _why&#8217;s excellent <a href="http://code.whytheluckystiff.net/hpricot/">hpricot</a>) to do just that would be:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#!/usr/bin/env ruby</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'open-uri'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'hpricot'</span>
&nbsp;
routes = <span style="color:#006600; font-weight:bold;">&#40;</span>1..15<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_a</span>.<span style="color:#9900CC;">concat</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">24</span>,<span style="color:#006666;">28</span>,<span style="color:#006666;">37</span>,<span style="color:#006666;">44</span>,<span style="color:#006666;">49</span>,<span style="color:#006666;">50</span>,<span style="color:#006666;">51</span><span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
routes.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>route<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#9966CC; font-weight:bold;">begin</span>
    route_uri = <span style="color:#996600;">&quot;http://www.ridetherapid.org/ride/routes/#{route}/stops/&quot;</span>
    doc = Hpricot<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>route_uri<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    title = doc.<span style="color:#9900CC;">at</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;h1&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">children</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_s</span>.<span style="color:#9900CC;">strip</span>
    <span style="color:#CC0066; font-weight:bold;">puts</span> title
    stopList = doc.<span style="color:#9900CC;">search</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;div#stopList table tr&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&#40;</span>1..<span style="color:#9900CC;">stopList</span>.<span style="color:#9900CC;">size</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>row<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#9966CC; font-weight:bold;">unless</span> stopList<span style="color:#006600; font-weight:bold;">&#91;</span>row<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?
        uri = stopList<span style="color:#006600; font-weight:bold;">&#91;</span>row<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">at</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;a&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">attributes</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'href'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
        name = stopList<span style="color:#006600; font-weight:bold;">&#91;</span>row<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">at</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;a&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">children</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_s</span>
        coords = uri.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>q=<span style="color:#006600; font-weight:bold;">&#40;</span>\d<span style="color:#006600; font-weight:bold;">+</span>\.\d<span style="color:#006600; font-weight:bold;">+</span><span style="color:#006600; font-weight:bold;">&#41;</span>,\<span style="color:#006600; font-weight:bold;">+</span><span style="color:#006600; font-weight:bold;">&#40;</span>.<span style="color:#006600; font-weight:bold;">*</span>?<span style="color:#006600; font-weight:bold;">&#41;</span>\<span style="color:#006600; font-weight:bold;">&amp;/</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">if</span> coords.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC00FF; font-weight:bold;">MatchData</span>
          latitude = coords<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>
          longitude = coords<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#93;</span>
          <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;#{name} on route #{route} is at #{latitude}, #{longitude}&quot;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> err
    <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Problem retrieving #{route_uri}&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>With this data available, it immediately becomes possible for local people and organizations to make use of it in a variety of ways&#8211;businesses could easily show the nearest bus stops to their locations, listing services can help visitors plan their routes, and those of us who aren&#8217;t fans of the flash-map could use other services to build alternatives.</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2006/09/scraping-grand-rapids-bus-routes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
