使用 Shell - 生成逐步驾驶导航
我很高兴地报告,本月我将回答读者关于如何编写脚本的问题。 不知道你们其他读者怎么了,但显然向我写信提出你们那些奇怪而具有挑战性的 shell 脚本难题现在并没有被列入候选名单。 读者 Paul M. 问
有没有办法抓取 Google 地图导航结果? 我想要的是文本(在 Ho-ho-kus Blvd 左转),而不是地图。 当我查看保存的结果页面时,我只能看到 CSS 和 JavaScript 代码。 但是,如果我手动复制并粘贴导航信息,就会出现逐步导航。 Dave,你有什么关于如何自动抓取逐步驾驶导航信息的建议吗?
啊,Google 地图上的那些狡猾的程序员让这件事变得非常困难! 四处查找由 maps.google.com 生成的源页面以查找导航信息,很明显他们使用 method=post 或其他高级方法来隐藏 URL 本身的起点和终点,以及一些非常高级的编码来使网页具有高度交互性。 所以见鬼去吧!
在经过大量挖掘并查看不同地图网站的工作方式后,我决定使用 Expedia.com 作为获取驾驶导航信息的最佳场所,这样我们就可以通过 URL 指定起点和终点,并且还可以理解输出。 首先,请在您的 Web 浏览器中查看 Expedia 的交互式驾驶导航,网址为 www.expedia.com/Directions。
在 Expedia 上,输入导航的起点和终点地址,您会发现所有信息都存储在一个可怕的复杂 URL 中,例如:www.expedia.com/pub/agent.dll?qscr=mrdr&rtyp=0&unit=0&lats1=38.89872&lons1=-77.036379&alts1=5&strt1=1600+Pennsylvania+Ave+NW&city1=Washington&stnm1=DC&zipc1=20006®n1=0&labl1=1600+Pennsylvania+Ave+NW%2C%0AWashington%2C+DC+20006&lats2=28.393142483519902&lons2=-81.57198620078931&alts2=5&strt2=N+World+Dr&city2=Orlando&stnm2=FL&zipc2=32830®n2=0&labl2=World+Dr%2C%0AOrlando%2C+FL+32830&。(眼尖的读者会注意到我正在为奥巴马一家提供前往迪士尼世界的驾驶路线。)
您可以从 URL 中删除一些多余的信息,并创建一个简单的命令行调用来获取地图和导航信息
start="strt1=1600+Pennsylvania+Ave+NW&city1=Washington&stnm1=DC" dest="strt2=N+World+Dr&city2=Orlando&stnm2=FL&zipc2=32830" curl --silent "http://www.expedia.com/pub/agent.dll?$start& ↪$dest&qscr=mrdr&rtyp=0&unit=0"
您可以看到 Expedia 需要一个解包的地址,并按街道地址、城市、州和邮政编码进行拆分(但如果它可以确定位置,则似乎可以跳过邮政编码,如所示开始以上)。
现在我们有了它,让我们使用 sed 仅提取结果表,而没有其他多余的信息。 这是通过手动分析源文件并注意到它全部在一个以以下 HTML 行开头的表中完成的
<TABLE BORDER=1 BORDERCOLOR=#E4E4E4 CELLSPACING=0 CELLPADDING=4>
毫不奇怪,我们寻找的表示表格结束的行是 </TABLE>。 这是让您可以根据需要对事物进行切片的代码
sed -n '/BORDERCOLOR=#E4E4E4/,/<\/TABLE>/p'
将它们放在一起并将输出保存到临时文件。 之后,下一个挑战是将 HTML 表格变成您可以实际阅读的内容。
为此,我们将求助于一个很棒的开源实用程序,称为 Lynx。 您的系统上可能已经安装了 Lynx,但如果您没有,请从 lynx.isc.org 获取 Lynx 基于文本的 Web 浏览器副本。 我们将使用它来解释 HTML 标记并将其转换为原始文本。
幸运的是,Lynx 非常擅长应对此类挑战,以下工作代码证明了这一点
curl --silent "http://www.expedia.com/pub/agent.dll?$start& ↪$dest&qscr=mrdr&rtyp=0&unit=0"| \ sed -n '/BORDERCOLOR=#E4E4E4/,/<\/TABLE>/p' | \ lynx -dump -stdin
是的,就是这样。 指定正确的起点和目的地,确保脚本知道在哪里可以找到系统上的 Lynx,输出将如下所示
Directions Distance Time Start: Depart Start on Local road(s) (East) 0.1 < 1min 1: Turn RIGHT (South) onto E Executive Ave NW 0.1 0:01 2: Turn LEFT (East) onto Alexander Hamilton Pl NW, then immediately turn RIGHT (South) onto 15th St NW 0.1 0:01 3: Turn LEFT (East) onto Pennsylvania Ave NW, then immediately turn RIGHT (South) onto 14th St NW 0.3 0:02 4: Keep STRAIGHT onto US-1 [14th St NW] 1.1 0:02 ... 22: Take Ramp (LEFT) onto Western Way (Disney World) 1.9 0:02 23: Turn LEFT (North) onto Bear Island Rd 2.1 0:03 24: Turn RIGHT (East) onto Floridian Way 0.3 0:01 25: Keep STRAIGHT onto World Dr 0.4 0:01 End: Arrive End < 0.1 < 1min Total Route 881 mi 13 hrs 2 mins
我将把它作为一个练习留给您,亲爱的读者,创建一个包装器,提示人们输入起点和终点地址,然后使用 curl 调用 Expedia 和随后的 Lynx 调用来显示逐步驾驶导航。
Dave Taylor 编写 shell 脚本已经很长时间了,30 年。 他是流行的 Wicked Cool Shell Scripts 的作者,可以在 Twitter 上找到 @DaveTaylor,更常见的是在 www.DaveTaylorOnline.com。