r/linux•
gdr

A modern way to mirror websites?

I happen to archive websites from time to time. Years ago, on Windows, I used Offline Explorer for that. It was a pretty decent tool, which usually downloaded all resources. Probably it does not do that well anymore.

On Linux we have wget -r and httrack, both with simple home brew HTML parsers. With all my sympathy for wget, they are just useless in these days of dynamic script loading and writing JS-heavy websites. A real web browser engine is needed to successfully mirror a site.

So my question is: which Linux programs or browser extensions are able to mirror a site built by 2013 standards?

EDIT: This seems to confuse people. I'm looking to save all interlinked pages in a domain, not to press ctrl-s in my browser.

Posted Sep 18, 2013, 1:19 PM UTC · edited

2220
[deleted]•

You're asking for scraping, not mirroring.

7
gdrOP•

As far as I understand, scraping = extracting data from parsed pages. Like going through a store and extracting names and prices to a database.

I want mirroring, a.k.a. spidering, which just saves all subpages of a website, along with resources needed to render them.

8
FrozenCow•

To me mirroring sounds more like proxying+caching somehow (which is why Squid was mentioned). You want to crawl+scrape the site.

I'm working on a crawler/scraper that should copy all pages/css/js/images to a directory (or rather a git repository). It's far from actually stable and full of hacks, but I'm using Zombie.js at the moment: http://zombie.labnotes.org/ Zombie.js is a programmable browser mostly used for testing websites. It is built on top of JSDom. JSDom is a implementation of a real browser DOM. That means it can (as far as it's implemented) load pages, run its javascript and parse CSS. JSDom is built on top of node.js.

You could also check out PhantomJS, which is a headless+scriptable webkit browser. I'd think there are scripts that should be able to download all files and follow all links in PhantomJS.

4
eldridcof•

If you build that out to call all assets on a page and execute the javascript and you run this as an actual crawler and not just as a one-off thing you're going to cause a lot of headaches for people running larger sites and get yourself blocked from sites who pay attention to things like ad metrics or analytics from javascript calls.

If you insist on doing it please for the love of god set your useragent to something that shows it's a crawler and not try to pretend you're a real browser.

Yes, other people are already doing it, and more people will I'm sure. Just venting because it causes lots of issues when someone suddenly starts crawling hundreds of thousands of webpages and sends javascript events that they clicked all the ads on all the pages.

1
FrozenCow•

Indeed, there is no intention to anger/break sites. It uses the useragent of ZombieJS atm. It doesn't yet have delays in crawling, but I want to add that too. The crawling doesn't have to be as fast as possible and it's used mostly for smallish static sites. A limit on the number of pages/assets/MB/etc will also come.

2
[deleted]•

[deleted]

1
[deleted]•

[deleted]

5
gdrOP•

Nice one.

1
shvelo•

Hmm that's interesting, I think you can write a Chrome packaged app for that, you could attach an event to onload that would save all the files in document.links, document.scripts, document.styleSheets and document.images.

Also you need a recursive function to analyze all css rules for @imports.

I guess all the dynamically loaded scripts will be present in document.scripts on onload.

2
gdrOP•

Yeah, I guess you could do that, but I'm not volunteering to write it :)

1
shvelo•

I don't have time for it, tho it would be the most useful thing I would write :D

1
ewood87•

This is something I've thought about in the past. Not from the same point of view as you're talking, but from the point of view of indexing (thing google search crawler). You could probably create crawler in much the same vain but have it download the contents of all crawled pages. See http://en.wikipedia.org/wiki/Web_crawler#Open-source_crawlers for some examples to get you started.

1
[deleted]•

[deleted]

1
totemcatcher•

I've come across a few sites that are difficult to leech due to the page content rendering based on anchors and javascript calls. I'm guessing this is one example of what you're talking about. Since all the content isn't organized into a sensible file structure to obtain with wget, you have to build a file structure from scratch for storing it locally -- possibly via rebasing all hyperlinks with hash codes.

e.g. Screen scrape, generate hash for every link, save resulting DOM as file. This could probably be done via envjs or zombie.

1
gdrOP•

A pure-AJAX site may be hard indeed, I wonder if there will be a day when we'll be able to leech these.

But even HTML-mostly pages, when downloaded with, say, wget - usually look like crap when you open them in browser afterwards.

1
mdadmfan•

Chrome's download web page?

squid?

0
gdrOP•

squid? I'd have to click on each and every link on the site so it gets cached. Not cool.

Could you elaborate on the Chrome thing?

1
mdadmfan•

Right click - Save As - Complete Webpage. That only grabs the page you are currently looking at.

wget -mk not doing what you want?

Moar wget

1
gdrOP•

I'm looking to spider hundreds to thousands of subpages.

wget works fine for html-only sites, that are a minority in 2013 (unfortunately).

1
[deleted]•

[deleted]

-3
gdrOP•

I'm looking to save all interlinked pages in a domain, not to press ctrl-s in my browser.

3
[deleted]•

The problem is, with 2013 standards, those interlinked pages do not exist until they are requested, generated with dynamic data, and provided to satisfy that request.

Since you do not have the backend code to generate these pages, or the front-end services to provide them, you will essentially need to do a scripted equivalent of Save Page As for each link followed.

How to go about this? I'm hoping someone else can chime in with an answer as I am not familiar with any product built for this.

3
badsuperblock•
2
gdrOP•

Thank you! The best answer in this thread :)

2