前边我们讲了使用urllib的request模块和parse模块来分别完成网络请求的发起和URL的正确处理。在这些过程中,我们不免会遇到一些错误,那么当错误发生时,我们应该怎么样避免程序出现我们意料之外的结果呢?其实答案与其他的场景没什么区别,那就是利用好异常捕获工具。
一、urllib中的异常模块:error
捕获异常的主要目的是在异常发生时,让程序继续执行我们设定好的动作(比如打印详细日志、将内存中的数据写入数据库、重新抓取当前网页等),而非直接终止,从而让我们的程序更加稳健。
urllib.error模块定义了在request模块调用过程中会产生的异常。
URLError是该模块的基类,由request产生的所有异常都可以通过它来捕获。HTTPError是URLError的子类,专门用来处理HTTP请求相关的错误,如认证失败、网页不存在等。ContentTooShortError是指下载的数据量比预期小,它在我们使用urllib.request.urlretrieve()方法下载网页到本地时可能会触发,触发条件就是下载的内容长度小于header中Content-Length的取值。
我们用一个简单的例子来演示下error模块的使用。
from urllib.request import urlopen
from urllib.error import URLError, HTTPError
try:
response = request.urlopen('https://www.baidu.com/nothing.html')
except HTTPError as e:
print('******code*****')
print(e.code)
print('\n')
print('******reason*****')
print(e.reason)
print('\n')
print('******headers*****')
print(e.headers)
print('\n')
print('******error*****')
print(e)
print('\n')
except error.URLError as e:
print(e.reason)
print(e)
else:
print('看到我说明你请求成功了!')
finally:
print('无论如何你都会看到我!')
输出如下:
******code***** 404 ******reason***** Not Found ******headers***** Content-Length: 210 Content-Type: text/html; charset=iso-8859-1 Date: Wed, 01 Feb 2023 12:57:32 GMT Server: Apache Connection: close ******error***** HTTP Error 404: Not Found 无论如何你都会看到我!
可以看到,我们先检查是否出现了HTTPError,然后再检查是否出现了URLError,这是因为HTTPError是URLError的子类,包含更详细的信息,如HTTP状态码、请求头等。如果不是HTTPError那么我们再用URLError来捕获,看一下错误的原因是什么。
如果没有出现URLError,那理论上我们这次请求是成功的。
二、robotparser模块:网站可以爬取吗?
事实上,我们在抓取网页内容时,经常会忽略一些网站的提示。但是这些提示很可能是重要的。
比如一个网站提示了某个网页禁止抓取,那么这个时候我们强行抓取可能是有侵权甚至违法的风险。
又比如一个网站告知了你建议的抓取频率,但你并不遵循,那很有可能你的IP地址会被永久封禁,以后就再也不能访问该网站了。
那么我们应该如何获取并解析网站的提示呢?这就要用到robotparser模块了。
一、爬虫协议
robotparser模块用于分析网站的Robots协议,一般来说,该协议存放于站点根目录下,命名为robots.txt,比如https://www.douban.com/robots.txt就存储着豆瓣网站的Robots协议。
Robots协议又称爬虫协议、机器人协议,用于网站告诉搜索引擎和爬虫一些信息:
- 允许抓取路径和禁止抓取路径
- 允许哪些爬虫抓取网站内容
- 建议抓取频率
- 站点地图
- ……
比如豆瓣的爬虫协议为:
User-agent: *
Disallow: /subject_search
Disallow: /amazon_search
Disallow: /search
Disallow: /group/search
Disallow: /event/search
Disallow: /celebrities/search
Disallow: /location/drama/search
Disallow: /forum/
Disallow: /new_subject
Disallow: /service/iframe
Disallow: /j/
Disallow: /link2/
Disallow: /recommend/
Disallow: /doubanapp/card
Disallow: /update/topic/
Disallow: /share/
Disallow: /people//collect
Disallow: /people//wish
Disallow: /people//all
Disallow: /people//do
Allow: /ads.txt
Sitemap: https://www.douban.com/sitemap_index.xml
Sitemap: https://www.douban.com/sitemap_updated_index.xml# Crawl-delay: 5
User-agent: Wandoujia Spider
Disallow: /User-agent: Mediapartners-Google
Disallow: /subject_search
Disallow: /amazon_search
Disallow: /search
Disallow: /group/search
Disallow: /event/search
Disallow: /celebrities/search
Disallow: /location/drama/search
Disallow: /j/
二、robotparser常用方法
使用robotparser非常简单,我们用RobotFileParser类接受一个robots.txt文件链接参数即可。
urllib.robotparser.RobotFileParser(url='')
该类支持如下方法。
1. set_url()方法
该方法用于设置robots.txt文件的链接,实际上我们往往在创建RobotFileParser对象时就已经传入了链接,所以该方法经常用不到。
2. read()方法
该方法用于读取robots.txt文件并进行分析,在创建RobotFileParser对象后,我们必须要执行一次read()方法,不然其他所有的调用结果都没有意义。
3. parse()方法
该方法用来解析robots.txt文件,传入的参数是robots.txt某些行的内容,它会对其进行解析。
4. can_fetch()方法
该方法接受useragent和url两个参数,返回该UA(User-Agent,如某爬虫引擎、某搜索引擎)是否可以抓取这个url。
5. mtime()方法
该方法返回上次抓取和分析robots.txt文件的时间,这可以帮助我们判断是否应该更新robots.txt的信息。
6. modified()方法
该方法将当前时间设置为上次抓取和分析robots.txt的时间,也就是说下次我们再调用mtime()时,返回的就是此时的时间。
7. crawl_delay()方法
该方法返回网站针对某个UA(User-Agent)建议的两次抓取的时间间隔。
8. request_rate()方法
该方法返回网站指定的Request-rate: x/n,比如Request-rate: 12/1m代表每1分钟可以抓取12个页面。
9. site_maps()方法
该方法以列表格式返回站点的站点地图。
怎么说呢,这个方法还是有用的,尤其是对于大型爬虫或者搜索引擎。它能帮助我们自动解析不同站点对爬虫的要求。
不过对我们个人来说,我们一般会直接打开站点的robots.txt看一眼,大概了解以后就关掉。如果它的要求能满足我们的要求,那我们就满足它的要求。如果它的要求不能满足我们的要求,那我们自然就不会满足它的要求。
如果大家真的那么乖,也就没有所谓的反爬与反反爬了。
Python爬虫:urllib模块异常处理与robots.txt解析实战
本文介绍了Python爬虫中urllib模块的异常处理,包括HTTPError和URLError的捕获,以及如何使用robots.txt解析模块来理解网站的爬虫协议,确保合规抓取。通过实例展示了如何读取和分析robots.txt,获取网站的抓取限制和建议。
2345

被折叠的 条评论
为什么被折叠?



