一日一技:拼接个URL你也能搞错,还写个爬虫

网络 通信技术
如果你不知道这一点的话,你的爬虫在拼接子页面URL的时候可能就会出问题。网站也可以使用这个机制构造出一个蜜罐,根据标签拼出来的URL才是真正的子页面地址,而用当前页面URL去拼接的URL是蜜罐地址,爬虫访问进去以后,就会抓到假数据,或者被立即屏蔽。

在写爬虫的过程中,我们经常需要解析网站的列表页。例如下面这个例子:

 

  1. <html> 
  2.     <head> 
  3.         <meta charset="utf-8"
  4.         <title>测试相对路径</title> 
  5.     </head> 
  6.     <body> 
  7.         <div> 
  8.             <h1>书籍列表</h1> 
  9.             <ul> 
  10.                 <li><a href="http://127.0.0.1:8000/book/1.html">第一本书</a></li> 
  11.                 <li><a href="http://127.0.0.1:8000/book/2.html">第二本书</a></li> 
  12.                 <li><a href="http://127.0.0.1:8000/book/3.html">第三本书</a></li> 
  13.                 <li><a href="http://127.0.0.1:8000/book/4.html">第四本书</a></li> 
  14.                 <li><a href="http://127.0.0.1:8000/book/5.html">第五本书</a></li> 
  15.             </ul> 
  16.         </div> 
  17.     </body> 
  18. </html> 

 

运行效果如下图所示:

这种情况下,我想获取每一项的URL非常简单,直接写一个XPath就可以了,如下图所示:

仔细观察你会发现,每一个连接的URL都是以http://127.0.0.1:8000开头的。而当前列表页的地址也是http://127.0.0.1:8000。所以为了简单起见,标签里面可以使用相对路径:

 

  1. <html> 
  2.     <head> 
  3.         <meta charset="utf-8"
  4.         <title>测试相对路径</title> 
  5.     </head> 
  6.     <body> 
  7.         <div> 
  8.             <h1>书籍列表</h1> 
  9.             <ul> 
  10.                 <li><a href="/book/1.html">第一本书</a></li> 
  11.                 <li><a href="/book/2.html">第二本书</a></li> 
  12.                 <li><a href="/book/3.html">第三本书</a></li> 
  13.                 <li><a href="/book/4.html">第四本书</a></li> 
  14.                 <li><a href="/book/5.html">第五本书</a></li> 
  15.             </ul> 
  16.         </div> 
  17.     </body> 
  18. </html> 

 

运行效果如下图所示,用XPath只能提取到半截URL:

但是浏览器可以正确识别这样的相对地址,并且当你点击的时候,它能自动跳转到正确的地址:

相对路径如果是以/开头,那么就会在相对路径前面拼接上网站的主域名。

但如果当前列表页的地址跟链接的相对路径有一部分重叠怎么办?如下图所示:

当前页面的地址是http://127.0.0.1:8000/book。而相对地址是/book/1.html。这种情况下,还可以进一步简化,在相对路径的前面不要加斜杠,把HTML改成:

 

  1. <html> 
  2.     <head> 
  3.         <meta charset="utf-8"
  4.         <title>测试相对路径</title> 
  5.     </head> 
  6.     <body> 
  7.         <div> 
  8.             <h1>书籍列表</h1> 
  9.             <ul> 
  10.                 <li><a href="1.html">第一本书</a></li> 
  11.                 <li><a href="2.html">第二本书</a></li> 
  12.                 <li><a href="3.html">第三本书</a></li> 
  13.                 <li><a href="4.html">第四本书</a></li> 
  14.                 <li><a href="5.html">第五本书</a></li> 
  15.             </ul> 
  16.         </div> 
  17.     </body> 
  18. </html> 

 

运行效果如下图所示:

这种情况下,浏览器依然能给正确识别,如下图所示:

浏览器知道,如果相对路径没有用/开头,那么它就会把当前页面的URL与相对路径拼接起来。但需要注意的是,在拼接的时候,会取最右侧斜杠左边的部分。而右边的部分会丢弃。就相当于拼接文件地址的时候,用这个文件所在的文件夹来拼接新的地址。如下图所示:

如果你记不住怎么区分的话,你可以使用Python自带的urllib.parse.urljoin来连接,如下图所示:

看到这里,你可能觉得我今天又水了一篇文章。这么简单的东西也值得写一篇文章来讲?

那么我们来看下面这个例子:

域名是http://127.0.0.1:8000/book/index.html,相对域名是1.html,但为什么浏览器自动识别出来的URL是www.kingname.info/1.html?

这个问题的关键,在于源代码里面的标签:

  1. <html> 
  2.     <head> 
  3.         <meta charset="utf-8"
  4.         <title>测试相对路径</title> 
  5.         <base href="http://www.kingname.info"
  6.     </head> 
  7.     <body> 
  8.         <div> 
  9.             <h1>书籍列表</h1> 
  10.             <ul> 
  11.                 <li><a href="1.html">第一本书</a></li> 
  12.                 <li><a href="2.html">第二本书</a></li> 
  13.                 <li><a href="3.html">第三本书</a></li> 
  14.                 <li><a href="4.html">第四本书</a></li> 
  15.                 <li><a href="5.html">第五本书</a></li> 
  16.             </ul> 
  17.         </div> 
  18.     </body> 
  19. </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

 

责任编辑:武晓燕 来源: 未闻Code
相关推荐

2023-10-28 12:14:35

爬虫JavaScriptObject

2022-01-26 07:35:10

爬虫Requestsgzip

2021-09-26 05:01:55

Scrapy项目爬虫

2021-06-08 21:36:24

PyCharm爬虫Scrapy

2021-12-15 22:04:11

浏览器重复登录

2021-04-27 22:15:02

Selenium浏览器爬虫

2021-10-15 21:08:31

PandasExcel对象

2020-12-04 06:39:25

爬虫网页

2021-04-12 21:19:01

PythonMakefile项目

2021-04-05 14:47:55

Python多线程事件监控

2021-03-12 21:19:15

Python链式调用

2021-09-13 20:38:47

Python链式调用

2022-03-12 20:38:14

网页Python测试

2022-06-28 09:31:44

LinuxmacOS系统

2021-04-19 23:29:44

MakefilemacOSLinux

2021-03-18 23:28:45

Python反斜杠字符串

2021-07-27 21:32:57

Python 延迟调用

2021-05-08 19:33:51

移除字符零宽

2021-10-03 20:08:29

HTTP2Scrapy

2021-05-10 19:07:18

冗余代码Python
点赞
收藏

51CTO技术栈公众号