編寫爬蟲竟然成了“面向監(jiān)獄編程”,就是因為不懂Robots協(xié)議
編寫Python爬蟲很容易,不過要想安全地編寫Python爬蟲,就需要了解更多的至少,不光是技術(shù)上的,還有法律上的,Robots協(xié)議就是其中之一,如果不了解Robots協(xié)議,抓取了不該抓取的東西,可能會面臨牢獄之災(zāi)哦!
1. Robots協(xié)議簡介
Robots協(xié)議也稱作爬蟲協(xié)議、機(jī)器人協(xié)議,它的全名是網(wǎng)絡(luò)爬蟲排除標(biāo)準(zhǔn)(Robots Exclusing Protocol),用來告訴爬蟲和搜索引擎哪些頁面可以抓取,哪些不可以抓取。該協(xié)議的內(nèi)容通常放在一個名為robots.txt的文本文件中,該文件一般位于網(wǎng)站的根目錄下。
注意,robots.txt文件中的內(nèi)容只是告訴爬蟲應(yīng)該抓取什么,不應(yīng)該抓取什么,但并不是通過技術(shù)手段阻止爬蟲抓取那些被禁止的資源,而只是通知爬蟲而已。盡管編寫爬蟲可以不遵循robots.txt文件的描述,但作為一只有道德、有文化、有紀(jì)律的爬蟲,應(yīng)該盡量遵循robots.txt文件描述的規(guī)則。否則,有可能會引起法律糾紛。
當(dāng)爬蟲訪問一個網(wǎng)站時,首先會檢查這個網(wǎng)址根目錄下是否存在robots.txt文件,如果存在,爬蟲就會根據(jù)該文件中定義的抓取范圍來抓取Web資源。如果這個文件并不存在,爬蟲就會抓取這個網(wǎng)站所有可直接訪問的頁面。下面來看一個robots.txt文件的例子:
- User-agent:*
- Disallow:/
- Allow:/test/
這個抓取規(guī)則首先告訴爬蟲對所有的爬蟲有效,而且除了test目錄外的任何資源都不允許抓取。如果將這個robots.txt文件放在某個網(wǎng)站的根目錄,那么搜索引擎的爬蟲就會只抓取test目錄下的資源,我們會發(fā)現(xiàn)搜索引擎中再也查不到其他目錄下的資源了。
上面的User-agent描述了爬蟲的名字,這里將其設(shè)置為*,則表示對所有的爬蟲有效,我們還可以特指某些爬蟲,如下面的設(shè)置明確指定百度爬蟲。
- User-agent:BaiduSpider
robots.txt文件中有2個重要的授權(quán)指令:Disallow和Allow,前者表示禁止抓取,后者表示運(yùn)行抓取。也就是說,Disallow是黑名單,Allow是白名單。 例如,下面是一些Robots協(xié)議的例子。
1. 禁止所有爬蟲抓取網(wǎng)站所有的資源
- User-agent:*
- Disallow:/
2. 禁止所有爬蟲抓取網(wǎng)站/private和/person目錄中的資源
- User-agent: *
- Disallow: /private/
- Disallow:/person/
3. 只禁止百度爬蟲抓取網(wǎng)站資源
- User-agent:BaiduSpider
- Disallow:/
很多搜索引擎的爬蟲都有特定的名稱,表1列出了一些常用的爬蟲名稱。
表1 常用的爬蟲名稱
2. 分析Robots協(xié)議
Robots協(xié)議并不需要我們自己去分析,urllib庫的robotparser模塊提供了相應(yīng)的API來解析robots.txt文件,這就是RobotFileParser類。可以用多種方式使用RobotFileParser類。例如,可以通過set_url方法設(shè)置robots.txt文件的URL,然后進(jìn)行分析,代碼如下:
- form urllib.robotparser import RobotFileParser
- robot = RobotFileParser()
- robot.set_url('https://www.jd.com/robots.txt')
- robot.read()
- print(robot.can_fetch('*','https://www.jd.com/test.js'))
其中can_fetch方法用來獲得該網(wǎng)站某一個URL根據(jù)Robots協(xié)議是否有權(quán)抓取,如果可以抓取,返回True,否則返回False。
RobotFileParser類的構(gòu)造方法也可以接受一個URL,然后使用can_fetch方法判斷是否可以抓取某一個頁面。
- robot = RobotFileParser('https://www.jd.com/robots.txt')
- print(robot.can_fetch('*','https://www.jd.com/test.js'))
下面的案例使用了parse方法指定robots.txt文件的數(shù)據(jù),并輸出不同的URL是否允許抓取,這是另外一種使用RobotFileParser類的方式。
- from urllib.robotparser import RobotFileParser
- from urllib import request
- robot = RobotFileParser()
- url = 'https://www.jianshu.com/robots.txt'
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36',
- 'Host': 'www.jianshu.com',
- }
- req = request.Request(url=url, headers=headers)
- # 抓取robots.txt文件的內(nèi)容,并提交給parse方法進(jìn)行分析
- robot.parse( request.urlopen(req).read().decode('utf-8').split('\n'))
- # 輸出True
- print(robot.can_fetch('*','https://www.jd.com'))
- # 輸出True
- print(robot.can_fetch('*','https://www.jianshu.com/p/92f6ac2c350f'))
- # 輸出False
- print(robot.can_fetch('*','https://www.jianshu.com/search?q=Python&page=1&type=note'))
運(yùn)行結(jié)果如下:
- True
- True
- False
本文轉(zhuǎn)載自微信公眾號「極客起源」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系極客起源公眾號。