views:

538

answers:

7

I'd like to write some code which looks at a website and its assets and creates some stats and a report. Assets would include images. I'd like to be able to trace links, or at least try to identify menus on the page. I'd also like to take a guess at what CMS created the site, based on class names and such.

I'm going to assume that the site is reasonably static, or is driven by a CMS, but is not something like an RIA.

Ideas about how I might progress.

1) Load site into an iFrame. This would be nice because I could parse it with jQuery. Or could I? Seems like I'd be hampered by cross-site scripting rules. I've seen suggestions to get around those problems, but I'm assuming browsers will continue to clamp down on such things. Would a bookmarklet help?

2) A Firefox add-on. This would let me get around the cross-site scripting problems, right? Seems doable, because debugging tools for Firefox (and GreaseMonkey, for that matter) let you do all kinds of things.

3) Grab the site on the server side. Use libraries on the server to parse.

4) YQL. Isn't this pretty much built for parsing sites?

+3  A: 

You should simply fetch the source (XHTML/HTML) and parse it. You can do that in almost any modern programming language. From your own computer that is connected to Internet.

iframe is a widget for displaying HTML content, it's not a technology for data analysis. You can analyse data without displaying it anywhere. You don't even need a browser.

Tools in languages like Python, Java, PHP are certainly more powerful for your tasks than Javascript or whatever you have in those Firefox extensions.

It also does not matter what technology is behind the website. XHTML/HTML is just a string of characters no matter how a browser renders it. To find your "assets" you will simply look for specific HTML tags like "img", "object" etc.

zilupe
Thanks. My thought with the iFrame was to make the browser do the parsing work so I could simply look at the DOM. This would also let me get CSS attributes of tags. A visual display would be nice, as I could highlight items or let the use hover over them to get info. But I'm looking for all pros and cons so your opinion is helpful.
Nosredna
You can analyse the DOM in PHP (http://uk.php.net/manual/en/intro.dom.php)
Rich Bradshaw
Also, parsing the meta generator tag would get the CMS for at least a few of them.
Rich Bradshaw
+3  A: 

I think an writing an extension to Firebug would proabably be one of the easiest way to do with. For instance YSlow has been developed on top of Firebug and it provides some of the features you're looking for (e.g. image, CSS and Javascript-summaries).

Yrlec
YSlow is definitely the way to go, as Carl said. However, I would argue that YSlow provides *all* of the features you request, including reports. Be sure to check out the Exceptional Performance group that discusses YSlow and performance in general:http://tech.groups.yahoo.com/group/exceptional-performance/
David Lantner
Ok, except for guessing the CMS / framework that the site is using. :)
David Lantner
+6  A: 

My suggestion would be:

a) Chose a scripting language. I suggest Perl or Python: also curl+bash but it bad no exception handling.

b) Load the home page via a script, using a python or perl library. Try Perl Mechanize module: search.cpan.org/~petdance/WWW-Mechanize-1.54/lib/WWW/Mechanize/Examples.pod

Python has plenty of built-in module, try a look also at www.feedparser.org

c) Inspect the server header (via the HTTP HEAD command) to find application server name. If you are lucky you will also find the CMS name (i.d. WordPress, etc).

d) Use Google XML API to ask something like "link:sitedomain.com" to find out links pointing to the site: again you will find code examples for Python on google home page. Also asking domain ranking to Google can be helpful.

e)You can collect the data in a SQLite db, then post process them in Excel.

daitangio
+2  A: 

That really depends on the scale of your project. If it’s just casual, not fully automated, I’d strongly suggest a Firefox Addon.

I’m right in the middle of similar project. It has to analyze the DOM of a page generated using Javascript. Writing a server-side browser was too difficult, so we turned to some other technologies: Adobe AIR, Firefox Addons, userscripts, etc.

Fx addon is great, if you don’t need the automation. A script can analyze the page, show you the results, ask you to correct the parts, that it is uncertain of and finally post the data to some backend. You have access to all of the DOM, so you don’t need to write a JS/CSS/HTML/whatever parser (that would be hell of a job!)

Another way is Adobe AIR. Here, you have more control over the application — you can launch it in the background, doing all the parsing and analyzing without your interaction. The downside is — you don’t have access to all DOM of the pages. The only way to go pass this is to set up a simple proxy, that fetches target URL, adds some Javascript (to create a trusted-untrusted sandbox bridge)… It’s a dirty hack, but it works.

Edit: In Adobe AIR, there are two ways to access a foreign website’s DOM:

  • Load it via Ajax, create HTMLLoader object, and feed the response into it (loadString method IIRC)
  • Create an iframe, and load the site in untrusted sandbox.

I don’t remember why, but the first method failed for me, so I had to use the other one (i think there was some security reasons involved, that I couldn’t workaround). And I had to create a sandbox, to access site’s DOM. Here’s a bit about dealing with sandbox bridges. The idea is to create a proxy, that adds a simple JS, that creates childSandboxBridge and exposes some methods to the parent (in this case: the AIR application). The script contents is something like:

window.childSandboxBridge = {
   // ... some methods returning data
}

(be careful — there are limitations of what can be passed via the sandbox bridge — no complex objects for sure! use only the primitive types)

So, the proxy basically tampered with all the requests that returned HTML or XHTML. All other was just passed through unchanged. I’ve done this using Apache + PHP, but could be done with a real proxy with some plugins/custom modules for sure. This way I had the access to DOM of any site.

end of edit.

The third way I know of, the hardest way — set up an environment similar to those on browsershots. Then you’re using firefox with automation. If you have a Mac OS X on a server, you could play with ActionScript, to do the automation for you.

So, to sum up:

  • PHP/server-side script — you have to implement your own browser, JS engine, CSS parser, etc, etc. Fully under control and automated instead.
  • Firefox Addon — has access to DOM and all stuff. Requires user to operate it (or at least an open firefox session with some kind of autoreload). Nice interface for a user to guide the whole process.
  • Adobe AIR — requires a working desktop computer, more difficult than creating a Fx addon, but more powerful.
  • Automated browser — more of a desktop programming issue that webdevelopment. Can be set up on a linux terminal without graphical environment. Requires master hacking skills. :)
Maciej Łebkowski
Great answer. I've done Adobe AIR before. Can you elaborate a bit on this? "The only way to go pass this is to set up a simple proxy, that fetches target URL, adds some Javascript (to create a trusted-untrusted sandbox bridge)… It’s a dirty hack, but it works."
Nosredna
edited my answer to add more about the Adobe AIR method. Didn’t choose this method after all, so my knowledge is a little limited. :)
Maciej Łebkowski
+2  A: 

I suggest you try option #4 first (YQL): The reason being that it looks like this might get you all the data you need and you could then build your tool as a website or such where you could get info about a site without actually having to go to the page in your browser. If YQL works for what you need, then it looks like you'd have the most flexibility with this option.

If YQL doesn't pan out, then I suggest you go with option #2 (a firefox addon).

I think you should probably try and stay away from Option #1 (the Iframe) because of the cross-site scripting issues you already are aware of.

Also, I have used Option #3 (Grab the site on the server side) and one problem I've ran into in the past is the site being grabbed loading content after the fact using AJAX calls. At the time I didn't find a good way to grab the full content of pages that use AJAX - SO BE WARY OF THAT OBSTACLE! Other people here have ran into that also, see this: http://stackoverflow.com/questions/206855/scrape-a-dynamic-website

THE AJAX DYNAMIC CONTENT ISSUE: There may be some solutions to the ajax issue, such as using AJAX itself to grab the content and using the evalScripts:true parameter. See the following articles for more info and an issue you might need to be aware of with how evaluated javascript from the content being grabbed works:

Prototype library: http://www.prototypejs.org/api/ajax/updater

Message Board: http://www.crackajax.net/forums/index.php?action=vthread&forum=3&topic=17

Or if you are willing to spend money, take a look at this: http://aptana.com/jaxer/guide/develop_sandbox.html

Here is an ugly (but maybe useful) example of using a .NET component called WebRobot to scrap content from a dynamic AJAX enabled site such as Digg.com. http://www.vbdotnetheaven.com/UploadFile/fsjr/ajaxwebscraping09072006000229AM/ajaxwebscraping.aspx

Also here is a general article on using PHP and the Curl library to scrap all the links from a web page. However, I'm not sure if this article and the Curl library covers the AJAX content issue: http://www.merchantos.com/makebeta/php/scraping-links-with-php/

One thing I just thought of that might work is:

  1. grab the content and evaluate it using AJAX.
  2. send the content to your server.
  3. evaluate the page, links, etc..
  4. [OPTIONAL] save the content as a local page on your server .
  5. return the statistics info back to the page.
  6. [OPTIONAL] display cached local version with highlighting.

^Note: If saving a local version, you will want to use regular expressions to convert relative link paths (for images especially) to be correct.

Good luck! Just please be aware of the AJAX issue. Many sites nowadays load content dynamically using AJAX. Digg.com does, MSN.com does for it's news feeds, etc...

Joe Bubna
This is a great answer.
Nosredna
A: 

Being primarily a .Net programmer these days, my advice would be to use C# or some other language with .Net bindings. Use the WebBrowser control to load the page, and then iterate through the elements in the document (via GetElementsByTagName()) to get links, images, etc. With a little extra work (parsing the BASE tag, if available), you can resolve src and href attributes into URL's and use the HttpWebRequest to send HEAD requests for the target images to determine their sizes. That should give you an idea of how graphically intensive the page is, if that's something you're interested in. Additional items you might be interested in including in your stats could include backlinks / pagerank (via Google API), whether the page validates as HTML or XHTML, what percentage of links link to URL's in the same domain versus off-site, and, if possible, Google rankings for the page for various search strings (dunno if that's programmatically available, though).

Dathan
A: 

I would use a script (or a compiled app depending on language of choice) written in a language that has strong support for networking and text parsing/regular expressions.

  • Perl
  • Python
  • .NET language of choice
  • Java

whatever language you are most comfortable with. A basic stand alone script/app keeps you from needing to worry too much about browser integration and security issues.

James Conigliaro