]> git.street.me.uk Git - andy/viking.git/blob - tools/gcget
Merge pull request #32 from davidedelvento/installnotes
[andy/viking.git] / tools / gcget
1 #!/usr/bin/env python
2
3 #
4 # THIS IS NO LONGER SUPPORTED
5 #
6 print """
7 This script no longer works after the geocaching.com website update see:
8  http://blog.geocaching.com/2011/05/preview-of-geocaching-com-may-4th-website-release/
9
10 It is now recommended to use the geo-* tools instead:
11  http://geo.rkkda.com/
12 """
13 import sys
14 sys.exit(1)
15
16 #
17 # One day this script could be resurrected, as the geo-* tools are not perhaps the fastest...
18 #
19
20 #
21 # gcget -- screen scrape Geocaching.com's annoying web interface
22 #          aka SHOW ME THE CACHE!!!
23 #
24 # Copyright 2007, Evan Battaglia
25 # Distributed under the terms of the GPL v2.
26 #
27 #
28 # requires module mechanize
29 #
30
31 # DEFAULT USERNAME AND PASSWORD: THESE ARE OVERWRITTEN BY COMMAND-LINE OPTIONS
32
33 USER="username"
34 PASS="password"
35
36 # docs needed!
37 # this has some extra args in:
38 # gcget lat,lon maxnumgcs [maxdist] [threshold]
39 # threshold -- if find more than this # of geocaches, don't get ANY,
40 # instead give warning and quit
41
42 import sys
43 import getopt
44
45 def help():
46    print """gcget v0.1
47 This program is free software, distributed under the terms of the GNU GPL v2.
48
49 Usage: gcget [-u username] [-p password] lat,lon maxnumberofgcs [maxdistance] [threshold]
50 Downloads up to maxnumberofgcs at a distance of up to maxdistance from lat,lon.
51 If we number of geocaches within maxdistance is above threshold, don't download any
52   geocaches, just give a warning and quit.
53
54 If username and password are not given, will use default values hard-coded in script.
55
56 Happy caching!!!
57 """
58
59 #
60 # PARSE OPTIONS: USERNAME AND PASSWORD
61 #
62 #
63 #
64 try:
65   opts, args = getopt.gnu_getopt(sys.argv[1:], "u:p:d", ["help"])
66 except getopt.GetoptError:
67   # print help information and exit:
68   help()
69   sys.exit(2)
70
71 DEBUG = False
72
73 for o, a in opts:
74   if o == "-p":
75     PASS = a
76   if o == "-u":
77     USER = a
78   if o == "--help" or o == "-h":
79     help()
80     sys.exit()
81   if o == "-d":
82     DEBUG = True
83
84 if len(args) < 2:
85   help()
86   sys.exit()
87
88 #########################
89 #ll = args[0].split(",")
90 #lat = ll[0]
91 #lon = ll[1]
92 #The following line replaced the previous 3 lines.
93 lat, lon = args[0].split(",")
94         
95 if len(args) >= 3:
96   maxdist = args[2]
97 else:
98   maxdist = "999"
99
100 if len(args) >= 4:
101   threshold = int(args[3])
102 else:
103   threshold = 1000000;
104
105 # rounds up to multiples of 20. 20
106 n = int((int(args[1])+19)/20)
107
108 import re
109 from mechanize import Browser
110 import ClientForm
111
112 # get magic number for "Next" button.
113 # this is normally 16 (link hidden is $ctl16), unless there are less than 10 pages of results,
114 # in which case it will be less (e.g. 09 for 3 pages of results)
115 def getmagicnumber(b):
116   for i in range(16,0,-1):
117     if re.compile("pgrBottom.ctl%02d" % i).search(b.response().get_data()):
118       return i
119   return None
120
121 b=Browser()
122 b.open("http://geocaching.com/seek/")
123 b.follow_link(text="Log in")
124 b.select_form(nr=0)
125 # The Username and Password fields on the Login form changed
126 b["ctl00$ContentBody$myUsername"] = USER
127 b["ctl00$ContentBody$myPassword"] = PASS
128 b.submit()
129
130 magicnumber = 0 # the ctl number of Next. get only once
131
132 try: b.select_form("form4")
133 except: pass
134 try:
135   b.select_form("form4")
136 except:
137   b.select_form("form4")
138   print >> sys.stderr, "Invalid username/password"
139   if DEBUG:
140     f=open("gcget.badlogin.html","w")
141     f.write(b.response().get_data())
142     f.close()
143     print >> sys.stderr, "Dumping last HTML page recieved into gcget.badlogin.html"
144   sys.exit()
145
146 b["origin_lat"] = lat
147 b["origin_long"] = lon
148 b["dist"] = maxdist
149 b.submit()
150
151 thresholdre = re.compile("Total Records: <b>([0-9]*)</b>")
152 m = thresholdre.search(b.response().get_data())
153 if m:
154   if int(m.group(1)) > threshold:
155     sys.stderr.write("THRESHOLD %d > %d\n" % (int(m.group(1)), threshold))
156     sys.exit(4)
157   else:
158     records = int(m.group(1))
159     sys.stderr.write("ok found %d, getting min(%d,%d) gcs\n" % (int(m.group(1)), int(records), int(args[1])))
160 else:
161   print "can't find total records"
162   sys.exit(0)
163
164 pages = 0
165 # (records+19)/20 is the max pages
166 for ii in range(min(n,(records+19)/20)):
167   try:
168     b.select_form(nr=0)
169     b['CID'] = [i.name for i in b.find_control('CID').items]
170     b.submit()
171   except:
172     break
173
174   # only print one header, start of xml file
175   lines = b.response().get_data().split("\n")
176   if ii == 0:
177     print "\n".join(lines[0:2])
178
179   # core
180   print "\n".join(lines[2:-1])
181
182   print "</waypoint>"
183
184   pages += 1
185   sys.stderr.write("i")
186   sys.stderr.flush()
187
188   b.back()
189
190   if not magicnumber:
191     magicnumber = getmagicnumber(b)
192     if not magicnumber:
193 #      print "couldn't find magic number!" # why does this happen?
194       break
195
196   b.select_form(nr=0)
197   [f for f in b.forms()][0].new_control("hidden", "ctl00$ContentBody$pgrBottom$ctl%02d" % magicnumber, {})
198   b.submit()
199
200 sys.stderr.write("\n")
201
202 if pages:
203   print "</loc>"
204
205 #  f=open("delmeNOW","w")
206 #  f.write(b.response().get_data())
207 #  f.close()
208