2018-05-28 08:50:30 +08:00
|
|
|
|
## 网络爬虫和相关工具
|
|
|
|
|
|
|
|
|
|
### 网络爬虫
|
|
|
|
|
|
|
|
|
|
网络爬虫(web crawler),以前经常称之为网络蜘蛛(spider),是按照一定的规则自动浏览万维网并获取信息的机器人程序(或脚本),曾经被广泛的应用于互联网搜索引擎。使用过互联网和浏览器的人都知道,网页中除了供用户阅读的文字信息之外,还包含一些超链接。网络爬虫系统正是通过网页中的超链接信息不断获得网络上的其它页面。正因如此,网络数据采集的过程就像一个爬虫或者蜘蛛在网络上漫游,所以才被形象的称为网络爬虫或者网络蜘蛛。
|
|
|
|
|
|
|
|
|
|
#### 爬虫的应用领域
|
|
|
|
|
|
|
|
|
|
在理想的状态下,所有ICP(Internet Content Provider)都应该为自己的网站提供API接口来共享它们允许其他程序获取的数据,在这种情况下爬虫就不是必需品,国内比较有名的电商平台(如淘宝、京东等)、社交平台(如腾讯微博等)等网站都提供了自己的Open API,但是这类Open API通常会对可以抓取的数据以及抓取数据的频率进行限制。对于大多数的公司而言,及时的获取行业相关数据是企业生存的重要环节之一,然而大部分企业在行业数据方面的匮乏是其与生俱来的短板,合理的利用爬虫来获取数据并从中提取出有价值的信息是至关重要的。当然爬虫还有很多重要的应用领域,以下列举了其中的一部分:
|
|
|
|
|
|
|
|
|
|
1. 搜索引擎
|
|
|
|
|
2. 新闻聚合
|
|
|
|
|
3. 社交应用
|
|
|
|
|
4. 舆情监控
|
|
|
|
|
5. 行业数据
|
|
|
|
|
|
|
|
|
|
### 合法性和背景调研
|
|
|
|
|
|
|
|
|
|
#### 爬虫合法性探讨
|
|
|
|
|
|
|
|
|
|
1. 网络爬虫领域目前还属于拓荒阶段,虽然互联网世界已经通过自己的游戏规则建立起一定的道德规范(Robots协议,全称是“网络爬虫排除标准”),但法律部分还在建立和完善中,也就是说,现在这个领域暂时还是灰色地带。
|
|
|
|
|
2. “法不禁止即为许可”,如果爬虫就像浏览器一样获取的是前端显示的数据(网页上的公开信息)而不是网站后台的私密敏感信息,就不太担心法律法规的约束,因为目前大数据产业链的发展速度远远超过了法律的完善程度。
|
|
|
|
|
3. 在爬取网站的时候,需要限制自己的爬虫遵守Robots协议,同时控制网络爬虫程序的抓取数据的速度;在使用数据的时候,必须要尊重网站的知识产权(从Web 2.0时代开始,虽然Web上的数据很多都是由用户提供的,但是网站平台是投入了运营成本的,当用户在注册和发布内容时,平台通常就已经获得了对数据的所有权、使用权和分发权)。如果违反了这些规定,在打官司的时候败诉几率相当高。
|
|
|
|
|
|
|
|
|
|
#### Robots.txt文件
|
|
|
|
|
|
|
|
|
|
大多数网站都会定义robots.txt文件,下面以淘宝的[robots.txt](http://www.taobao.com/robots.txt)文件为例,看看该网站对爬虫有哪些限制。
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
User-agent: Baiduspider
|
|
|
|
|
Allow: /article
|
|
|
|
|
Allow: /oshtml
|
|
|
|
|
Disallow: /product/
|
|
|
|
|
Disallow: /
|
|
|
|
|
|
|
|
|
|
User-Agent: Googlebot
|
|
|
|
|
Allow: /article
|
|
|
|
|
Allow: /oshtml
|
|
|
|
|
Allow: /product
|
|
|
|
|
Allow: /spu
|
|
|
|
|
Allow: /dianpu
|
|
|
|
|
Allow: /oversea
|
|
|
|
|
Allow: /list
|
|
|
|
|
Disallow: /
|
|
|
|
|
|
|
|
|
|
User-agent: Bingbot
|
|
|
|
|
Allow: /article
|
|
|
|
|
Allow: /oshtml
|
|
|
|
|
Allow: /product
|
|
|
|
|
Allow: /spu
|
|
|
|
|
Allow: /dianpu
|
|
|
|
|
Allow: /oversea
|
|
|
|
|
Allow: /list
|
|
|
|
|
Disallow: /
|
|
|
|
|
|
|
|
|
|
User-Agent: 360Spider
|
|
|
|
|
Allow: /article
|
|
|
|
|
Allow: /oshtml
|
|
|
|
|
Disallow: /
|
|
|
|
|
|
|
|
|
|
User-Agent: Yisouspider
|
|
|
|
|
Allow: /article
|
|
|
|
|
Allow: /oshtml
|
|
|
|
|
Disallow: /
|
|
|
|
|
|
|
|
|
|
User-Agent: Sogouspider
|
|
|
|
|
Allow: /article
|
|
|
|
|
Allow: /oshtml
|
|
|
|
|
Allow: /product
|
|
|
|
|
Disallow: /
|
|
|
|
|
|
|
|
|
|
User-Agent: Yahoo! Slurp
|
|
|
|
|
Allow: /product
|
|
|
|
|
Allow: /spu
|
|
|
|
|
Allow: /dianpu
|
|
|
|
|
Allow: /oversea
|
|
|
|
|
Allow: /list
|
|
|
|
|
Disallow: /
|
|
|
|
|
|
|
|
|
|
User-Agent: *
|
|
|
|
|
Disallow: /
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
注意上面robots.txt第一段的最后一行,通过设置“Disallow: /”禁止百度爬虫访问除了“Allow”规定页面外的其他所有页面。因此当你在百度搜索“淘宝”的时候,搜索结果下方会出现:“由于该网站的robots.txt文件存在限制指令(限制搜索引擎抓取),系统无法提供该页面的内容描述”。百度作为一个搜索引擎,至少在表面上遵守了淘宝网的robots.txt协议,所以用户不能从百度上搜索到淘宝内部的产品信息。
|
|
|
|
|
|
|
|
|
|
![](./res/baidu-search-taobao.png)
|
|
|
|
|
|
|
|
|
|
### 相关工具介绍
|
|
|
|
|
|
|
|
|
|
#### HTTP协议
|
|
|
|
|
|
2018-05-28 19:44:44 +08:00
|
|
|
|
在开始讲解爬虫之前,我们稍微对HTTP(超文本传输协议)做一些回顾,因为我们在网页上看到的内容通常是浏览器执行HTML语言得到的结果,而HTTP就是传输HTML数据的协议。HTTP是构建于TCP(传输控制协议)之上应用级协议,它利用了TCP提供的可靠的传输服务实现了Web应用中的数据交换。按照维基百科上的介绍,设计HTTP最初的目的是为了提供一种发布和接收[HTML](https://zh.wikipedia.org/wiki/HTML)页面的方法,也就是说这个协议是浏览器和Web服务器之间传输的数据的载体。关于这个协议的详细信息以及目前的发展状况,大家可以阅读阮一峰老师的[《HTTP 协议入门》](http://www.ruanyifeng.com/blog/2016/08/http.html)、[《互联网协议入门》](http://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html)系列以及[《图解HTTPS协议》](http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html)进行了解,下图是我在2009年9月10日凌晨4点在四川省网络通信技术重点实验室用开源协议分析工具Ethereal(抓包工具WireShark的前身)截取的访问百度首页时的HTTP请求和响应的报文(协议数据),由于Ethereal截取的是经过网络适配器的数据,因此可以清晰的看到从物理链路层到应用层的协议数据。
|
2018-05-28 08:50:30 +08:00
|
|
|
|
|
2018-05-28 19:44:44 +08:00
|
|
|
|
HTTP请求(请求行+请求头+空行+[消息体]):
|
|
|
|
|
|
|
|
|
|
![](/Users/Hao/Desktop/Python-100-Days/Day41-55/res/http-request.png)
|
|
|
|
|
|
|
|
|
|
HTTP响应(响应行+响应头+空行+消息体):
|
|
|
|
|
|
|
|
|
|
![](/Users/Hao/Desktop/Python-100-Days/Day41-55/res/http-response.png)
|
|
|
|
|
|
|
|
|
|
> 说明:但愿这两张如同泛黄的照片般的截图帮助你大概的了解到HTTP是一个怎样的协议。
|
2018-05-28 08:50:30 +08:00
|
|
|
|
|
|
|
|
|
#### 相关工具
|
|
|
|
|
|
|
|
|
|
1. Chrome Developer Tools
|
|
|
|
|
|
|
|
|
|
![](./res/chrome-developer-tools.png)
|
|
|
|
|
|
|
|
|
|
2. POSTMAN
|
|
|
|
|
|
|
|
|
|
![](./res/postman.png)
|
|
|
|
|
|
|
|
|
|
3. HTTPie
|
|
|
|
|
|
|
|
|
|
```Shell
|
|
|
|
|
$ http --header http://www.scu.edu.cn
|
|
|
|
|
HTTP/1.1 200 OK
|
|
|
|
|
Accept-Ranges: bytes
|
|
|
|
|
Cache-Control: private, max-age=600
|
|
|
|
|
Connection: Keep-Alive
|
|
|
|
|
Content-Encoding: gzip
|
|
|
|
|
Content-Language: zh-CN
|
|
|
|
|
Content-Length: 14403
|
|
|
|
|
Content-Type: text/html
|
|
|
|
|
Date: Sun, 27 May 2018 15:38:25 GMT
|
|
|
|
|
ETag: "e6ec-56d3032d70a32-gzip"
|
|
|
|
|
Expires: Sun, 27 May 2018 15:48:25 GMT
|
|
|
|
|
Keep-Alive: timeout=5, max=100
|
|
|
|
|
Last-Modified: Sun, 27 May 2018 13:44:22 GMT
|
|
|
|
|
Server: VWebServer
|
|
|
|
|
Vary: User-Agent,Accept-Encoding
|
|
|
|
|
X-Frame-Options: SAMEORIGIN
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
4. BuiltWith:识别网站使用的技术
|
|
|
|
|
|
|
|
|
|
```Python
|
|
|
|
|
>>>
|
|
|
|
|
>>> import builtwith
|
|
|
|
|
>>> builtwith.parse('http://www.bootcss.com/')
|
|
|
|
|
{'web-servers': ['Nginx'], 'font-scripts': ['Font Awesome'], 'javascript-frameworks': ['Lo-dash', 'Underscore.js', 'Vue.js', 'Zepto', 'jQuery'], 'web-frameworks': ['Twitter Bootstrap']}
|
|
|
|
|
>>>
|
|
|
|
|
>>> import ssl
|
|
|
|
|
>>> ssl._create_default_https_context = ssl._create_unverified_context
|
|
|
|
|
>>> builtwith.parse('https://www.jianshu.com/')
|
|
|
|
|
{'web-servers': ['Tengine'], 'web-frameworks': ['Twitter Bootstrap', 'Ruby on Rails'], 'programming-languages': ['Ruby']}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
5. python-whois:查询网站的所有者
|
|
|
|
|
|
|
|
|
|
```Python
|
|
|
|
|
>>>
|
|
|
|
|
>>> import whois
|
|
|
|
|
>>> whois.whois('baidu.com')
|
|
|
|
|
{'domain_name': ['BAIDU.COM', 'baidu.com'], 'registrar': 'MarkMonitor, Inc.', 'whois_server': 'whois.markmonitor.com', 'referral_url': None, 'updated_date': [datetime.datetime(2017, 7, 28, 2, 36, 28), datetime.datetime(2017, 7, 27, 19, 36, 28)], 'creation_date': [datetime.datetime(1999, 10, 11, 11, 5, 17), datetime.datetime(1999, 10, 11, 4, 5, 17)], 'expiration_date': [datetime.datetime(2026, 10, 11, 11, 5, 17), datetime.datetime(2026, 10, 11, 0, 0)], 'name_servers': ['DNS.BAIDU.COM', 'NS2.BAIDU.COM', 'NS3.BAIDU.COM', 'NS4.BAIDU.COM', 'NS7.BAIDU.COM', 'dns.baidu.com', 'ns4.baidu.com', 'ns3.baidu.com', 'ns7.baidu.com', 'ns2.baidu.com'], 'status': ['clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited', 'clientTransferProhibited https://icann.org/epp#clientTransferProhibited', 'clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited', 'serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited', 'serverTransferProhibited https://icann.org/epp#serverTransferProhibited', 'serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited', 'clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited)', 'clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited)', 'clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited)', 'serverUpdateProhibited (https://www.icann.org/epp#serverUpdateProhibited)', 'serverTransferProhibited (https://www.icann.org/epp#serverTransferProhibited)', 'serverDeleteProhibited (https://www.icann.org/epp#serverDeleteProhibited)'], 'emails': ['abusecomplaints@markmonitor.com', 'whoisrelay@markmonitor.com'], 'dnssec': 'unsigned', 'name': None, 'org': 'Beijing Baidu Netcom Science Technology Co., Ltd.', 'address': None, 'city': None, 'state': 'Beijing', 'zipcode': None, 'country': 'CN'}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
6. robotparser:解析robots.txt的工具
|
|
|
|
|
|
2018-05-28 19:44:44 +08:00
|
|
|
|
```Python
|
|
|
|
|
>>> from urllib import robotparser
|
|
|
|
|
>>> parser = robotparser.RobotFileParser()
|
|
|
|
|
>>> parser.set_url('https://www.taobao.com/robots.txt')
|
|
|
|
|
>>> parser.read()
|
|
|
|
|
>>> parser.can_fetch('Hellokitty', 'http://www.taobao.com/article')
|
|
|
|
|
False
|
|
|
|
|
>>> parser.can_fetch('Baiduspider', 'http://www.taobao.com/article')
|
|
|
|
|
True
|
|
|
|
|
>>> parser.can_fetch('Baiduspider', 'http://www.taobao.com/product')
|
|
|
|
|
False
|
|
|
|
|
```
|
|
|
|
|
|
2018-05-28 08:50:30 +08:00
|
|
|
|
### 一个简单的爬虫
|
|
|
|
|
|
|
|
|
|
构造一个爬虫一般分为数据采集、数据处理和数据存储三个部分的内容。
|
|
|
|
|
|
|
|
|
|
首先我们要设定抓取的目标并获取网页。
|
|
|
|
|
|
|
|
|
|
1. 设置重试次数。
|
|
|
|
|
2. 设置用户代理。
|
|
|
|
|
|