websucker.py 3.22 KB
Newer Older
1 2 3 4
#! /usr/bin/env python

"""A variant on webchecker that creates a mirror copy of a remote site."""

5
__version__ = "$Revision$"
6 7 8 9 10 11

import os
import sys
import urllib
import getopt

12
import webchecker
13 14 15

# Extract real version number if necessary
if __version__[0] == '$':
16
    _v = __version__.split()
17
    if len(_v) == 3:
Guido van Rossum's avatar
Guido van Rossum committed
18
        __version__ = _v[1]
19 20

def main():
21
    verbose = webchecker.VERBOSE
22
    try:
Guido van Rossum's avatar
Guido van Rossum committed
23
        opts, args = getopt.getopt(sys.argv[1:], "qv")
24
    except getopt.error, msg:
Guido van Rossum's avatar
Guido van Rossum committed
25 26 27
        print msg
        print "usage:", sys.argv[0], "[-qv] ... [rooturl] ..."
        return 2
28
    for o, a in opts:
Guido van Rossum's avatar
Guido van Rossum committed
29 30 31 32
        if o == "-q":
            verbose = 0
        if o == "-v":
            verbose = verbose + 1
33 34
    c = Sucker()
    c.setflags(verbose=verbose)
35
    c.urlopener.addheaders = [
Guido van Rossum's avatar
Guido van Rossum committed
36 37
            ('User-agent', 'websucker/%s' % __version__),
        ]
38
    for arg in args:
Guido van Rossum's avatar
Guido van Rossum committed
39 40
        print "Adding root", arg
        c.addroot(arg)
41 42 43 44 45
    print "Run..."
    c.run()

class Sucker(webchecker.Checker):

46
    checkext = 0
Guido van Rossum's avatar
Guido van Rossum committed
47 48 49 50 51
    nonames = 1

    # SAM 11/13/99: in general, URLs are now URL pairs.
    # Since we've suppressed name anchor checking,
    # we can ignore the second dimension.
52

Guido van Rossum's avatar
Guido van Rossum committed
53 54
    def readhtml(self, url_pair):
        url = url_pair[0]
Guido van Rossum's avatar
Guido van Rossum committed
55 56 57 58 59
        text = None
        path = self.savefilename(url)
        try:
            f = open(path, "rb")
        except IOError:
Guido van Rossum's avatar
Guido van Rossum committed
60
            f = self.openpage(url_pair)
Guido van Rossum's avatar
Guido van Rossum committed
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
            if f:
                info = f.info()
                nurl = f.geturl()
                if nurl != url:
                    url = nurl
                    path = self.savefilename(url)
                text = f.read()
                f.close()
                self.savefile(text, path)
                if not self.checkforhtml(info, url):
                    text = None
        else:
            if self.checkforhtml({}, url):
                text = f.read()
            f.close()
        return text, url
77 78

    def savefile(self, text, path):
Guido van Rossum's avatar
Guido van Rossum committed
79 80
        dir, base = os.path.split(path)
        makedirs(dir)
81 82 83 84 85 86 87
        try:
            f = open(path, "wb")
            f.write(text)
            f.close()
            self.message("saved %s", path)
        except IOError, msg:
            self.message("didn't save %s: %s", path, str(msg))
88 89

    def savefilename(self, url):
Guido van Rossum's avatar
Guido van Rossum committed
90 91
        type, rest = urllib.splittype(url)
        host, path = urllib.splithost(rest)
92
        path = path.lstrip("/")
Guido van Rossum's avatar
Guido van Rossum committed
93 94
        user, host = urllib.splituser(host)
        host, port = urllib.splitnport(host)
95
        host = host.lower()
96
        if not path or path[-1] == "/":
97
            path = path + "index.html"
Guido van Rossum's avatar
Guido van Rossum committed
98
        if os.sep != "/":
99
            path = os.sep.join(path.split("/"))
100
        path = os.path.join(host, path)
Guido van Rossum's avatar
Guido van Rossum committed
101
        return path
102 103

def makedirs(dir):
104 105 106 107 108 109 110 111 112 113
    if not dir:
        return
    if os.path.exists(dir):
        if not os.path.isdir(dir):
            try:
                os.rename(dir, dir + ".bak")
                os.mkdir(dir)
                os.rename(dir + ".bak", os.path.join(dir, "index.html"))
            except os.error:
                pass
Guido van Rossum's avatar
Guido van Rossum committed
114
        return
115 116
    head, tail = os.path.split(dir)
    if not tail:
Guido van Rossum's avatar
Guido van Rossum committed
117 118
        print "Huh?  Don't know how to make dir", dir
        return
119 120 121 122 123
    makedirs(head)
    os.mkdir(dir, 0777)

if __name__ == '__main__':
    sys.exit(main() or 0)