一日一技:拼接个URL你也能搞错,还写个爬虫
在写爬虫的过程中,我们经常需要解析网站的列表页。例如下面这个例子:
- <html>
- <head>
- <meta charset="utf-8">
- <title>测试相对路径</title>
- </head>
- <body>
- <div>
- <h1>书籍列表</h1>
- <ul>
- <li><a href="http://127.0.0.1:8000/book/1.html">第一本书</a></li>
- <li><a href="http://127.0.0.1:8000/book/2.html">第二本书</a></li>
- <li><a href="http://127.0.0.1:8000/book/3.html">第三本书</a></li>
- <li><a href="http://127.0.0.1:8000/book/4.html">第四本书</a></li>
- <li><a href="http://127.0.0.1:8000/book/5.html">第五本书</a></li>
- </ul>
- </div>
- </body>
- </html>
运行效果如下图所示:
这种情况下,我想获取每一项的URL非常简单,直接写一个XPath就可以了,如下图所示:
仔细观察你会发现,每一个连接的URL都是以http://127.0.0.1:8000开头的。而当前列表页的地址也是http://127.0.0.1:8000。所以为了简单起见,标签里面可以使用相对路径:
- <html>
- <head>
- <meta charset="utf-8">
- <title>测试相对路径</title>
- </head>
- <body>
- <div>
- <h1>书籍列表</h1>
- <ul>
- <li><a href="/book/1.html">第一本书</a></li>
- <li><a href="/book/2.html">第二本书</a></li>
- <li><a href="/book/3.html">第三本书</a></li>
- <li><a href="/book/4.html">第四本书</a></li>
- <li><a href="/book/5.html">第五本书</a></li>
- </ul>
- </div>
- </body>
- </html>
运行效果如下图所示,用XPath只能提取到半截URL:
但是浏览器可以正确识别这样的相对地址,并且当你点击的时候,它能自动跳转到正确的地址:
相对路径如果是以/开头,那么就会在相对路径前面拼接上网站的主域名。
但如果当前列表页的地址跟链接的相对路径有一部分重叠怎么办?如下图所示:
当前页面的地址是http://127.0.0.1:8000/book。而相对地址是/book/1.html。这种情况下,还可以进一步简化,在相对路径的前面不要加斜杠,把HTML改成:
- <html>
- <head>
- <meta charset="utf-8">
- <title>测试相对路径</title>
- </head>
- <body>
- <div>
- <h1>书籍列表</h1>
- <ul>
- <li><a href="1.html">第一本书</a></li>
- <li><a href="2.html">第二本书</a></li>
- <li><a href="3.html">第三本书</a></li>
- <li><a href="4.html">第四本书</a></li>
- <li><a href="5.html">第五本书</a></li>
- </ul>
- </div>
- </body>
- </html>
运行效果如下图所示:
这种情况下,浏览器依然能给正确识别,如下图所示:
浏览器知道,如果相对路径没有用/开头,那么它就会把当前页面的URL与相对路径拼接起来。但需要注意的是,在拼接的时候,会取最右侧斜杠左边的部分。而右边的部分会丢弃。就相当于拼接文件地址的时候,用这个文件所在的文件夹来拼接新的地址。如下图所示:
如果你记不住怎么区分的话,你可以使用Python自带的urllib.parse.urljoin来连接,如下图所示:
看到这里,你可能觉得我今天又水了一篇文章。这么简单的东西也值得写一篇文章来讲?
那么我们来看下面这个例子:
域名是http://127.0.0.1:8000/book/index.html,相对域名是1.html,但为什么浏览器自动识别出来的URL是www.kingname.info/1.html?
这个问题的关键,在于源代码里面的标签:
- <html>
- <head>
- <meta charset="utf-8">
- <title>测试相对路径</title>
- <base href="http://www.kingname.info">
- </head>
- <body>
- <div>
- <h1>书籍列表</h1>
- <ul>
- <li><a href="1.html">第一本书</a></li>
- <li><a href="2.html">第二本书</a></li>
- <li><a href="3.html">第三本书</a></li>
- <li><a href="4.html">第四本书</a></li>
- <li><a href="5.html">第五本书</a></li>
- </ul>
- </div>
- </body>
- </html>
如果HTML代码头部有标签,那么,它的href属性的值,会被用来跟相对路径拼接出一个绝对路径,而不会再用当前页面的URL来拼接。
如果你不知道这一点的话,你的爬虫在拼接子页面URL的时候可能就会出问题。网站也可以使用这个机制构造出一个蜜罐,根据标签拼出来的URL才是真正的子页面地址,而用当前页面URL去拼接的URL是蜜罐地址,爬虫访问进去以后,就会抓到假数据,或者被立即屏蔽。
关于标签的详细说明,大家可以阅读:: The Document Base URL element[1]。
参考文献
[1] The Document Base URL element: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
相关文章
- 微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)
- 前端发展空间大?后端才是王道?开发者何去何从?
- 深度学习如何将个性化引入互联网
- MIT 提出Network Dissection框架,全自动窥探神经网络训练的黑箱
- 挨踢部落直播课堂第二期:移动互联网产品中如何用好HTML5?
- DB2实用程序的性能优化
- 挨踢部落故事汇(21):半路接手项目有多难?教你做个接盘侠高手!
- >>【直播间】移动互联网产品中如何用好HTML5?
- 我的深度学习开发环境详解:TensorFlow + Docker + PyCharm等,你的呢?
- 挨踢部落故事汇(19):转行做IT技术,你怎么能不知道这些事情?!
- 【干货】手机QQ及Qzone速度优化实践
- 专访Linux基金会执行董事Jim Zemlin:开源从曲高和寡到妇孺皆知
- 挨踢部落故事汇(18):程序猿与代码的基情
- Android Studio中使用apt
- 开启HSTS让浏览器强制跳转HTTPS访问
- 你的车有了这样的车载操作系统,溜到飞起
- 如何让深度学习在手机应用上也能加速跑?看完这篇文章你就知道了
- 挨踢部落故事汇(17):我与永恒之蓝战斗的两天两夜
- 专访DeepMap COO罗维:自动驾驶时代,创业公司如何在高精度地图领域突围?
- Access数据库转Excel工作簿2法