4 # gcget -- screen scrape Geocaching.com's annoying web interface
5 # aka SHOW ME THE CACHE!!!
7 # Copyright 2007, Evan Battaglia
8 # Distributed under the terms of the GPL v2.
11 # requires module mechanize
14 # DEFAULT USERNAME AND PASSWORD: THESE ARE OVERWRITTEN BY COMMAND-LINE OPTIONS
20 # this has some extra args in:
21 # gcget lat,lon maxnumgcs [maxdist] [threshold]
22 # threshold -- if find more than this # of geocaches, don't get ANY,
23 # instead give warning and quit
30 This program is free software, distributed under the terms of the GNU GPL v2.
32 Usage: gcget [-u username] [-p password] lat,lon maxnumberofgcs [maxdistance] [threshold]
33 Downloads up to maxnumberofgcs at a distance of up to maxdistance from lat,lon.
34 If we number of geocaches within maxdistance is above threshold, don't download any
35 geocaches, just give a warning and quit.
37 If username and password are not given, will use default values hard-coded in script.
43 # PARSE OPTIONS: USERNAME AND PASSWORD
48 opts, args = getopt.gnu_getopt(sys.argv[1:], "u:p:", ["help"])
49 except getopt.GetoptError:
50 # print help information and exit:
59 if o == "--help" or o == "-h":
67 #########################
69 ll = args[0].split(",")
79 threshold = int(args[3])
83 # rounds up to multiples of 20. 20
84 n = int((int(args[1])+19)/20)
87 from mechanize import Browser
90 def getmagicnumber(b):
91 for i in range(16,0,-1):
92 if re.compile("pgrBottom..ctl%d" % i).search(b.response().get_data()):
97 b.open("http://geocaching.com/seek/")
98 b.follow_link(text_regex="log in")
100 b["myUsername"] = USER
101 b["myPassword"] = PASS
104 magicnumber = 0 # the ctl number of Next. get only once
106 try: b.select_form("form4")
108 b.select_form("form4")
109 b["origin_lat"] = lat
110 b["origin_long"] = lon
114 thresholdre = re.compile("Total Records: <b>([0-9]*)</b>")
115 m = thresholdre.search(b.response().get_data())
117 if int(m.group(1)) > threshold:
118 sys.stderr.write("THRESHOLD %d > %d\n" % (int(m.group(1)), threshold))
121 records = int(m.group(1))
122 sys.stderr.write("ok found %d, getting min(%d,%d) gcs\n" % (int(m.group(1)), int(records), int(args[1])))
124 print "can't find total records"
128 # (records+19)/20 is the max pages
129 for ii in range(min(n,(records+19)/20)):
132 b['CID'] = [i.name for i in b.find_control('CID').items]
137 # only print one header, start of xml file
138 lines = b.response().get_data().split("\n")
140 print "\n".join(lines[0:2])
143 print "\n".join(lines[2:-1])
148 sys.stderr.write("i")
154 magicnumber = getmagicnumber(b)
157 [f for f in b.forms()][0].new_control("hidden", "pgrBottom$_ctl%d" % magicnumber, {})
160 sys.stderr.write("\n")
165 # f=open("delmeNOW","w")
166 # f.write(b.response().get_data())