Add copyright
[viking/guyou.git] / tools / gcget
blobc6c850bacf0e58cc324b21fa4a320ef7b023593b
1 #!/usr/bin/env python
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
16 USER="username"
17 PASS="password"
19 # docs needed!
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
25 import sys
26 import getopt
28 def help():
29 print """gcget v0.1
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.
39 Happy caching!!!
40 """
43 # PARSE OPTIONS: USERNAME AND PASSWORD
47 try:
48 opts, args = getopt.gnu_getopt(sys.argv[1:], "u:p:d", ["help"])
49 except getopt.GetoptError:
50 # print help information and exit:
51 help()
52 sys.exit(2)
54 DEBUG = False
56 for o, a in opts:
57 if o == "-p":
58 PASS = a
59 if o == "-u":
60 USER = a
61 if o == "--help" or o == "-h":
62 help()
63 sys.exit()
64 if o == "-d":
65 DEBUG = True
67 if len(args) < 2:
68 help()
69 sys.exit()
71 #########################
73 ll = args[0].split(",")
74 lat = ll[0]
75 lon = ll[1]
77 if len(args) >= 3:
78 maxdist = args[2]
79 else:
80 maxdist = "999"
82 if len(args) >= 4:
83 threshold = int(args[3])
84 else:
85 threshold = 1000000;
87 # rounds up to multiples of 20. 20
88 n = int((int(args[1])+19)/20)
90 import re
91 from mechanize import Browser
92 import ClientForm
94 # get magic number for "Next" button.
95 # this is normally 16 (link hidden is $ctl16), unless there are less than 10 pages of results,
96 # in which case it will be less (e.g. 09 for 3 pages of results)
97 def getmagicnumber(b):
98 for i in range(16,0,-1):
99 if re.compile("pgrBottom.ctl%02d" % i).search(b.response().get_data()):
100 return i
101 return None
103 b=Browser()
104 b.open("http://geocaching.com/seek/")
105 b.follow_link(text="Log in")
106 b.select_form(nr=0)
107 b["myUsername"] = USER
108 b["myPassword"] = PASS
109 b.submit()
111 magicnumber = 0 # the ctl number of Next. get only once
113 try: b.select_form("form4")
114 except: pass
115 try:
116 b.select_form("form4")
117 except:
118 b.select_form("form4")
119 print >> sys.stderr, "Invalid username/password"
120 if DEBUG:
121 f=open("gcget.badlogin.html","w")
122 f.write(b.response().get_data())
123 f.close()
124 print >> sys.stderr, "Dumping last HTML page recieved into gcget.badlogin.html"
125 sys.exit()
127 b["origin_lat"] = lat
128 b["origin_long"] = lon
129 b["dist"] = maxdist
130 b.submit()
132 thresholdre = re.compile("Total Records: <b>([0-9]*)</b>")
133 m = thresholdre.search(b.response().get_data())
134 if m:
135 if int(m.group(1)) > threshold:
136 sys.stderr.write("THRESHOLD %d > %d\n" % (int(m.group(1)), threshold))
137 sys.exit(4)
138 else:
139 records = int(m.group(1))
140 sys.stderr.write("ok found %d, getting min(%d,%d) gcs\n" % (int(m.group(1)), int(records), int(args[1])))
141 else:
142 print "can't find total records"
143 sys.exit(0)
145 pages = 0
146 # (records+19)/20 is the max pages
147 for ii in range(min(n,(records+19)/20)):
148 try:
149 b.select_form(nr=0)
150 b['CID'] = [i.name for i in b.find_control('CID').items]
151 b.submit()
152 except:
153 break
155 # only print one header, start of xml file
156 lines = b.response().get_data().split("\n")
157 if ii == 0:
158 print "\n".join(lines[0:2])
160 # core
161 print "\n".join(lines[2:-1])
163 print "</waypoint>"
165 pages += 1
166 sys.stderr.write("i")
167 sys.stderr.flush()
169 b.back()
171 if not magicnumber:
172 magicnumber = getmagicnumber(b)
173 if not magicnumber:
174 # print "couldn't find magic number!" # why does this happen?
175 break
177 b.select_form(nr=0)
178 [f for f in b.forms()][0].new_control("hidden", "ctl00$ContentBody$pgrBottom$ctl%02d" % magicnumber, {})
179 b.submit()
181 sys.stderr.write("\n")
183 if pages:
184 print "</loc>"
186 # f=open("delmeNOW","w")
187 # f.write(b.response().get_data())
188 # f.close()