I originally posted this on Google's Search Appliance Group for work, however, there was an issue with Google's HTML editor that kept messing up and refusing to display it. One of the group admins was finally able to post it but they had to leave out some code in order to do it. It's presented here in its entirety.
In order to add Omniture's SiteCatalyst code to a Google Search Appliance you need to modify the raw XSLT stylesheet. The following customizations will insert the tracking code after the opening <body> tag on the search results page. As per the implementation requirements by Omniture, the code will also dynamically set s.prop1 to the search terms and s.prop2 to the number of results returned. If zero results are returned we populate s.prop2 with "zero" and not 0.
Before you implement these changes be sure to make a backup of your existing stylesheet.
Implementation
Step 1:
Add the following code to the end of the section where Google recommends you make customizations. Replace the "INSERT-DOMAIN-AND-PATH-TO-CODE" with the location where you uploaded the s_code.js file:
<!-- **********************************************************************
Add Omniture SiteCatalyst code (can be customized)
********************************************************************** -->
<xsl:template name="sitecatalyst">
<xsl:param name="query"/>
<xsl:param name="matches"/>
<xsl:comment>
SiteCatalyst code version: H.16.
Copyright 1997-2008 Omniture, Inc. More info available at
http://www.omniture.com
</xsl:comment>
<script language="JavaScript" type="text/javascript" src="INSERT-DOMAIN-AND-PATH-TO-CODE/s_code.js"></script>
<script language="JavaScript" type="text/javascript">
<xsl:comment>
s.prop1="<xsl:value-of select='$query'/>"
s.prop2="<xsl:value-of select='$matches'/>"
var s_code=s.t();if(s_code)document.write(s_code)
//</xsl:comment>
</script>
<script language="JavaScript" type="text/javascript">
<xsl:comment>
if(navigator.appVersion.indexOf('MSIE')>=0)document.write(unescape('%3C')+'\!-'+'-')
//</xsl:comment>
</script>
<xsl:comment>
End SiteCatalyst code version: H.16.
</xsl:comment>
</xsl:template>
Step 2:
Next, locate the XSL template named, search_results and place the following code after the opening <body> tag:
<!-- *** Add Omniture SiteCatalyst code *** -->
<xsl:choose>
<xsl:when test="RES">
<xsl:call-template name="sitecatalyst">
<xsl:with-param name="query" select="Q"/>
<xsl:with-param name="matches" select="RES/M"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="sitecatalyst">
<xsl:with-param name="query" select="Q"/>
<xsl:with-param name="matches" select="'zero'"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
Conclusion
Save your changes and you should be in business. The Google Search Protocol Reference states the XSL stylesheet cache is updated approximately every 15 minutes. I have found it can take a lot longer. In order to force it to refresh the stylesheet currently being requested simply add &proxyreload=1 to the end of your search URL.
A simple command line tool written in Python to get the latest METAR text from NOAA's Aviation Weather Center.
#! /usr/bin/env python
import BeautifulSoup
import optparse
import urllib
import urllib2
class Metars(object):
"""Gets latest METAR text given 4-letter ICAO station identifier(s) and returns a list."""
def __init__(self, stations):
self.stations = stations
def get_metars(self):
metars = []
url = 'http://adds.aviationweather.gov/metars/index.php'
user_agent = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)'
values = {'station_ids': self.stations}
headers = {'User-Agent': user_agent}
data = urllib.urlencode(values)
req = urllib2.Request(url, data, headers)
response = urllib2.urlopen(req)
page = response.read()
soup = BeautifulSoup.BeautifulSoup(page)
fontTag = soup.find('font')
stations = fontTag.findAllNext(text=True)
metars = [station for station in stations if station.strip('\n')]
return metars
def main():
p = optparse.OptionParser(description=' Returns latest METAR text given a 4-letter ICAO station identifier',
usage="usage: %prog station1[,station2]",
version="%prog 0.1")
options, arguments = p.parse_args()
if len(arguments) == 1:
stations = Metars(arguments[0])
observations = stations.get_metars()
if observations:
for observation in observations:
print observation
else:
p.print_help()
if __name__ == '__main__':
main()
To use it from the command line simply enter a comma separated list of 4-letter ICAO station identifiers.
$ ./metars.py cyvr,cyxx
CYVR 201500Z 00000KT 20SM SCT120 OVC170 05/02 A2979 RMK AC3AC5 SLP088
CYXX 201500Z 00000KT 30SM SCT120 BKN210 07/M02 A2979 RMK AC4CS2 VIRGA SLP090
You can also use it interactively within the Python shell like this,
>>> import metars
>>> stations = metars.Metars("cyvr,cyxx")
>>> observations = stations.get_metars()
>>> observations
[u'CYVR 201500Z 00000KT 20SM SCT120 OVC170 05/02 A2979 RMK AC3AC5 SLP088',
u'CYXX 201500Z 00000KT 30SM SCT120 BKN210 07/M02 A2979 RMK AC4CS2 VIRGA SLP090']
A list of weather stations can be found in the Aviation Weather Center's station.txt file.
In case you have never heard of Twitter, it's touted as, "a service for friends, family, and co-workers to communicate and stay connected through the exchange of quick, frequent answers to one simple question: What are you doing?"
It's free to join and fun to see what you can pack into a 140 character limit update.
You can follow my "tweets" here. See you online.
I was looking for a source code highlighting solution to colorize code I place into this blog. I found there are a number of solutions available. Many are external programs which run against the source file such as GNU Source-highlight, however, some are browser based and use JavaScript to markup the code in realtime as Syntax Highlighter does.
Pygments is an python based generic syntax highlighter that has
support for wide number of programming languages and markup
formats.
I need to replace ampersands in a text file with the HTML entity '&'. I could simply use Python's s
tring replace method, however, this will mess up my text if some of the ampersands have already been turned into HTML entities. The same is true if I use regular expressions to match a single '&'. What I really need to do is replace an ampersand providing it is not followed by 'amp;'.
Using negative lookahead assertion with our regular expression is the answer. Negative lookahead is used when you want to match something not followed by something else. It starts with (?! and finishes at the ).
Our expression now becomes: &(?!amp;) and means the text it contains, amp;, must not follow the
expression that preceeds it.
In this example I also added an expression to not match any HTML entity numbers as well.
>>> import re
>>> s = "<Title>Eugene's Software Emporium & Arcade</Title>"
>>> pattern = re.compile('&(?!#)(?!amp;)')
>>> if pattern.search(s):
... iterator = pattern.finditer(s)
... for match in iterator:
... print match.span()
...
(38, 39)
>>> s[match.start():match.end()]
'&'
>>>
The PythonInfo Wiki defines a a web framework as,
a collection of packages or modules which allow developers to write Web applications or services without having to handle such low-level details as protocols, sockets or process/thread management.
As a testiment to Python's power and simplicity it would seem that many developers have created
their own frameworks rather than use a solution already in existence. As a result one will find solutions
in various stages of development and feature implementation.
I have always tried to subscribe to the basic principle of using the right tool for the job.
With that in mind I have embarked on an exploratory journey to investigate some of Python's existing
Web frameworks with hopes of finding one that will work for a couple of big projects I have in the
works. My requirements are fairly simple; I do not want to learn a behemoth of an API that will take
months to figure out, yet I do not want something so simplistic that it will expect me to handle to many
low-level details. Finally, until I can bring my own server back online, the chosen framework needs to work with my current hosting provider, DreamHost.
The five high-level frameworks I am looking at include:
- Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Because Django was developed in a fast-paced newsroom environment, it was designed to make common Web-development tasks fast and easy.
- TurboGears builds on other open source projects. In TurboGears,
CherryPy controllers sit at the hub of your project. This is the
biggest area for integration. Providing tools that allow the controllers to more easily work with SQLObject databases, answer asynchronous calls from
MochiKit and render out completed Kid templates is where the big win will come.
- Pylons combines the very best ideas from the worlds of Ruby, Python and Perl, providing a structured but extremely flexible Python web framework. It's also one of the first projects to leverage the emerging WSGI standard, which allows extensive re-use and flexibility - but only if you need it. Out of the box, Pylons aims to make web development fast, flexible and easy.
- Webware is a suite of Python packages and tools
for developing object-oriented, web-based applications. The suite uses well known design patterns
and includes a fast Application Server, Servlets, Python Server Pages (PSP), Object-Relational Mapping,
Task Scheduling, Session Management, and many other features. Webware is very modular and easily extended.
- Zope is an open source application server for building content management systems, intranets, portals, and custom applications. The Zope community consists of hundreds of companies and thousands of developers all over the world, working on building the platform and Zope applications. Zope is written in Python.
While at LinuxFest Northwest 2008 in Bellingham, WA this past weekend I attended a session on natural language processing in Python presented by Sean Boisen. His slide presentation was done, not with PowerPoint, but with HTML Slidy, a browser based XHTML presentation framework. The best thing about HTML Slidy is that it is cross-browser compatible using simple XHTML, JavaScript and CSS, operates like PointPoint and best of all, is accessible.
The next time I have a presentation to make, HTML Slidy is definitely something I am going to try.
The other day I managed to secure the dining-guide.org domain name.
The Dining Guide will offer restaurant and cafe patrons a place to share their experiences with others. How many times have you had a bad experience in a restaurant and later talked with a friend to learn they had a simliar one? Would you rather know where the exceptional food and service is? Would you rather know a head of time if the restaurant is family friendly? I certainly would and that is one of the reasons why I am building the site.
I have seen many sites offering variations on this same theme, however, none of them have the feature sets and usability that I will be implementing on the Dining Guide site.
Stay tuned and be sure to watch the site over the next few weeks.
This is one of the sites I did for my company, Effigy Interactive, back in 2002. I broke every usability and accessibility rule creating it, however, most self-promotional sites usually do.
The Flash portion of the site is meant to be atmospheric and encourage the viewer to explore and discover. I never got around to finishing the html portion as I was to busy with customer sites and other paying projects.
Last month I picked myself up an 8GB Insignia Pilot video MP3 player from Best Buy for Christmas.
I looked at a number of MP3 players before deciding on the Insignia Pilot. I had two main requirements: it had to work with Linux and it had to support Ogg Vorbis audio. The Insignia Pilot does both of these and more. It supports an impressive list of formats: MP3, WMA, WMA Lossless, WMA DRM, WMA Pro, OGG, WAV, Audible, MPEG4 (30 fps), WMV (30 fps) and JPEG.
The Insignia Pilot supports 320x240 MPEG4 video at 30 fps. Very nice. The installation CD includes a Windows based application that will convert video clips and images into a format compatible with the Pilot. This is great if you are running Windows, however, not so helpful if you are running Linux.
Over the next few days I learned more about video codecs and encoding than I had planned to. The Anything But iPod site was a great source of information and thanks in part to this initial thread on supported video formats
, MPlayer and hours of reading the documentation for MEncoder
and Xvid followed by trial and error I have a workable solution.
First copy the DVD (which you own) to your hard drive using the following,
mplayer dvd://1 -dumpstream -dumpfile dump.vob
Next is the encoding process. The Pilot's screen is 320x240, however, if the DVD is in widescreen format and you want to preserve the ratio you need to scale the video to 320x176 instead.
mencoder dump.vob -aid 128 -oac mp3lame -lameopts cbr:br=96 -srate 44100 -af resample=44100:0:0 -af volume=20 \
-ovc lavc -lavcopts vcodec=mpeg4:mbd=1:vbitrate=384 -sws 2 -vf scale=320:176,harddup \
-noskip -skiplimit 1 -ffourcc XVID -ofps 29.97 -o output.avi
With the above settings I can encode the Matrix to 481.1 MB. For me, these settings provide a reasonable trade off of size over quality. If one wants a slightly higher quality you can change the audio and video bitrates to cbr:br=128 and vbitrate=512 respectively.