在Python2中,有urllib和urllib2两个库来实现请求的发送,而在Python3中,统一为了urllib,其官方文档链接为:https://docs.python.org/3/library/urllib.html。urllib是Python内置的HTTP请求库,它包含4个模块:

  • request:最基本的HTTP请求模块,可以用来模拟发送请求。
  • error:异常处理模块,如果出现请求错误,可以捕获异常,然后进行重试或其他操作。
  • parse:工具模块,提供了许多URL处理方法,如拆分、解析、合并等。
  • robotparser:主要用于识别网站的rebots.txt文件,然后判断哪些网站可以爬,哪些网站不可以爬。

request模块

urllib的request模块提供了最基本的构造HTTP请求的方法,使用它可以方便地实现请求的发送并得到响应,同时它还带有处理授权验证(authentication)、重定向(redirection)、浏览器Cookies以及其他内容。

1. urlopen( )

使用urlopen( )函数可以发送一个请求,urlopen( )函数的完整参数列表如下:

urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None,capath=None,cadefault=False,context=None)

用法可参考官方文档https://docs.python.org/3/library/urllib.request.html。

1)使用urlopen( )方法爬取网页源代码,url参数用于指定要请求的URL路径(未指定data参数时,默认使用GET请求方法)

#导入request模块
import urllib.request
#发出请求并返回响应
response = urllib.request.urlopen("https://www.python.org")
#打印响应返回的内容
print(response.read())

​ urlopen( )函数返回的是一个HTTPResponse对象,它包含了read( )、readinto( )、getheader(name)、getheaders( )、fileno( )等方法, 以及msg、version、status、reason、debuglevel、closed等属性。

#导入request模块
import urllib.request
#发出请求并得到响应
response = urllib.request.urlopen("https://www.python.org")
#查看响应的类型
print(type(response))
#打印响应状态码
print(response.status)
#打印请求头
print(response.getheaders())
#打印请求头中Server属性的值(表示服务端使用Web服务器是什么软件,如Tomcat、Nginx等)
print(response.getheader("Server"))

2)data参数可以设置请求要传递的参数,使用时需要使用bytes( )方法将参数转化为字节流编码格式的内容,即bytes类型;并且如果 使用了data参数,则请求方法就不再是GET方法了,而是POST方法。

import urllib.parse
import urllib.request
data = bytes(urllib.parse.urlencode({'word':'hello'}),encoding='utf-8')
response = urllib.request.urlopen('http://httpbin.org/post',data=data)
print(response.read())

​ 这里传递了一个参数word,值是hello。它需要被转码成bytes(字节流)类型。其中转字节流采用了bytes( )方法,该方法的第一个参 数是字符串类型,需要用urllib.parse模块里的urlencode( )方法将参数转换为字符串,bytes( )方法第二个参数指定编码格式。执行后, 通过观察返回的响应头里的Content-Type字段的值可以知道使用的是POST请求方法。

4)timeout参数可以设置超时时间,单位为秒,如果请求超过了设置的超时时间还没有得到响应,就会抛出异常。如果不指定timeout参 数,就会使用全局默认时间。它支持HTTP、HTTPS、FTP请求。

import urllib.request
#向百度发出请求,如果5秒内还没有得到响应,则抛出异常
response = urllib.request.urlopen('https://www.baidu.com',timeout=5)
print(response.read())

​ 可以通过设置这个超时时间来控制一个网页在长时间未响应时,就跳过它的抓取。这可以利用try except语句实现,如下:

import socket
import urllib.request
import urllib.error
try:
	response = urllib.request.urlopen('http://www.baidu.com',timeout=0.01)
except urllib.error.URLError as e:
	print(e.reason)
	print(socket.timeout)
	if isinstance(e.reason,socket.timeout):
		print('Time Out')

5)除了url、data、timeout这些参数外,还有context参数,它必须是ssl.SSLContext类型,用来制定SSL设置。此外,cafile和capath这两 个参数分别指定CA证书的和它的路径,这个在请求HTTPS链接时会有用,cadefault参数已经启用了,其默认值为false。


2. Request

使用urlopen( )方法可以实现最基本请求的发起,但不足以构建一个完整的请求。如果请求中需要加Headers等信息,则需要使用Request类来构建。它的构造方法如下:

class urllib.request.Request(url,data=None,headers={},origin_req_host=None,unverifiable=False,method=None)

url是必选参数,其余都是可选参数。

  • url:请求的URL。。

  • data:请求的参数。必须传bytes(字节流)类型的,如果是字典,可以先用urllib.parse模块里的urlencode( )编码。

  • headers:请求头。它是一个字典类型的数据。可以在构造Request对象时通过headers参数直接构造,也可以由Request对象调用add_header( )方法添加。添加请求头最常用的就是通过修改User-Agent来伪装浏览器,默认的User-Agent是Python-urllib,比如伪装火狐浏览器,可以将请求头中的User-Agent字段值设置为:

    ​ Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0

    可以去某个浏览器发送请求然后查看请求中的User-Agent字段的值。

  • origin_req_host:请求方的host名称或者IP地址。

  • unverifiable:该请求是否是无法验证的,默认为False,意思是说用户没有足够权限来选择接收这个请求的结果。例如,请求一个HTML文档中的图片,但是没有自动抓取图像的权限,这时unverifiable的值就是True。

  • method:请求使用的方法,类型是一个字符串,比如GET、POST。

通过Request类,一方面我们可以将请求独立成一个对象,另一方面可以更加丰富和灵活地配置参数。

1)基本使用

import urllib.request
#调用Request()方法返回一个Request类型对象
request = urllib.request.Request('https://python.org')
#使用urlopen发送请求时将Request类型对象传进去
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))

​ 它依旧是使用urlopen( )方法发送请求,只不过这次该方法的参数不再是URL,而是一个Request类型的对象。

2)设置请求头、请求参数。

from urllib import request,parse
url = 'http://httpbin.org/post'
#请求头
headers = {
	'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0',
	'Host':'httpbin.org'
}
param = {
	'name':'Germey'
}
data = bytes(parse.urlencode(param),encoding='utf-8')
req = request.Request(url=url,data=data,headers=headers,method='POST')
'''
也可以通过add_header()方法逐个添加请求头
req.add_header('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0')
'''
response = request.urlopen(req)
print(response.read().decode('utf-8'))


3. Handler、Opener

实现验证、代理设置、Cookies处理等功能需要使用Handler和Opener。可以将Handler理解为各种处理器,有专门处理登录验证的,有处理Cookie的,有处理代理设置的,利用它们,几乎可以做到HTTP请求中所有的事情。urllib.request模块里的BaseHandler类,是其他所有Handler的父类,提供了最基本的方法,例如default_open( )、protocol_request( )等。它的常用子类有:

  • HTTPDefaultErrorHandler:用于处理HTTP响应错误,错误都会抛出HTTPError类型的异常。
  • HTTPRedirectHandler:用于处理重定向。
  • HTTPCookieProcessor:用于处理Cookies。
  • ProxyHandler:用于设置代理,默认代理为空。
  • HTTPPasswordMgr:用于管理密码,它维护了用户名和密码的表。
  • HTTPBasicAuthHandler:用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。

更多的Handler类可参考官方文档:https://docs.python.org/3/library/urllib.request.html#urllib.request.BaseHandler。Handler需要和Opener(Opener对应的类为OpenerDirector)组合使用,通过Handler对象可以构建Opener对象,Opener对象可以调用open( )方法,open( )方法的返回类型和urlopen( )是一样的。

1)验证。有些网站在打开时就会弹出提示框,直接提示你输入用户名和密码,验证成功后才能查看页面,比如Tomcat管理页:

​ 请求这样带有验证的页面时,可以借助HTTPBasicAuthhandler完成,代码如下:

from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler,build_opener
from urllib.error import URLError
username = 'admin'
password = '123456'
#tomcat服务器管理页
url = 'http://localhost:8080/manager/html'
p = HTTPPasswordMgrWithDefaultRealm();
p.add_password(None,url,username,password)
auth_handler = HTTPBasicAuthHandler(p)
opener = build_opener(auth_handler)
try:
	result = opener.open(url)
	html = result.read().decode('utf-8')
	print(html)
except URLError as e:
	print(e.reason)

​ 该案例中,如果验证成功,则打印tomcat管理页的源代码。

2)实现代理。在做爬虫的时候,免不了要使用代理,如果要添加代理,可以使用ProxyHandler,其参数是一个字典,字典中键名协议类 型(比如HTTP或者HTTPS等),键值是代理连接,可以添加多个代理。

from urllib.error import URLError
from urllib.request import ProxyHandler,build_opener
#为了方便测试,在本地搭建了一个代理,运行在9743端口上
proxy_handler = ProxyHandler({
	'http':'http://127.0.0.1:9743',
	'http':'https://127.0.0.1:9743'
})
opener = build_opener(proxy_handler)
try:
	response = opener.open('https://www.baidu.com')
	print(response.read().decode('utf-8'))
except URLError as e:
	print(e.reason)

3)获取网站的Cookie。首先,必须声明一个CookieJar对象,然后利用HTTPCookieProcessor来构建一个Handler,最后利用 build_opener( )方法构建Opener,执行open( )方法即可。

import urllib.request,http.cookiejar

cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
#遍历cookies
for item in cookie:
	print(item.name+"="+item.value)

4)获取网站的Cookie并保存为文件。

import urllib.request,http.cookiejar

filename = 'cookies.txt'
cookie = http.cookiejar.MozillaCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True,ignore_expires=True)

​ 这里将CookieJar换成了MozillaCookieJar,它在生成文件时会用到,是CookieJar的子类,可以用来处理Cookies和文件相关的事件, 比如读取和保存Cookies,本例中将Cookies保存成了Mozilla型浏览器的Cookies格式,运行之后当前目录下生成了一个cookies.txt文 件,内容如下:


​ 另外,LWPCookieJar也可以读取和保存Cookies,但是保存的格式和MozillaCookieJar不一样,它会保存为libwww-perl(LWP)格式 的Cookies文件。要保存成LWP格式的Cookie文件,可以在声明时使用LWPCookieJar

cookie = http.cookiejar.LWPCookieJar(filename)

​ 此时生成的Cookies文件中的格式如下:

5)生成Cookies文件后,后续过程中会读取Cookies文件并进行利用。以LWPCookieJar格式的Cookie文件为例

import urllib.request,http.cookiejar

cookie = http.cookiejar.LWPCookieJar()
#加载Cookies文件
cookie.load('cookies.txt',ignore_discard=True,ignore_expires=True)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
#运行正常的话,会输出百度网页的源代码
print(response.read().decode('utf-8'))

以上是urllib库中request模块的基本用法,想实现更多的功能,可以参考官方文档:https://docs.python.org/3/library/urllib.request.html


error模块

urllib库中的error模块定义了由request模块产生的异常,使用request模块发送请求时,如果出现错误,便会抛出error模块中定义的异常。

1. URLError

URLError类来自urllib库的error模块,它继承自OSError类,是error异常模块的基类,request模块产生的异常都可以通过捕获这个类来处理。它有一个属性reason,表示错误的原因。

from urllib import request,error
try:
  #该url是不存在的,所以会产生异常
	response = request.urlopen('https://cuiqingcai.com/a.html')
except error.URLError as e:
  #由于访问的网页不存在,所以会打印Not Found
	print(e.reason)

2. HTTPError

HTTPError是URLError的子类,专用用来处理HTTP请求错误,比如认证请求失败等。它有如下3个属性:

  • code:HTTP状态码。
  • reason:同父类一样,表示错误的原因。
  • headers:请求头

1)捕获异常,查看HTTPError的三个属性。

from urllib import request,error
try:
  #此处访问了一个不存在的网页
	response = request.urlopen('https://cuiqingcai.com/indea.html')
except error.HTTPError as e:
	print(e.reason)
	print(e.code)
	print(e.headers)


2)因为URLError类是HTTPError的父类,所以在捕获异常时应先选择捕获子类的异常,再去捕获父类的异常。写法如下:

from urllib import request,error
try:
	response = request.urlopen('https://cuiqingcai.com/indea.html')
#先捕获子类异常
except error.HTTPError as e:
	print(e.reason)
	print(e.code)
	print(e.headers)
#后捕获父类异常
except error.URLError as e:
	print(e.reason)
#用else来处理正常的逻辑
else:
	print("Request Successfully")

​ 以上案例是一个较好的异常处理方法的格式。

3)有时候,reason属性返回的不一定时字符串,也可能是一个对象。

import socket
import urllib.request
import urllib.error
try:
  response = urllib.request.urlopen('https://www.baidu.com',timeout=0.01)
except urllib.error.URLError as e:
  print(type(e.reason))
  if isinstance(e.reason,socket.timeout):
    print('Time Out')


​ 设置超时时间0.01秒来强制抛出timeout异常,从运行结果中可以看到,reason属性的类型是socket.timeout类,所以可以使用 isinstance( )方法来判断它的类型,作出更详细的有针对性的处理。


parse模块

urllib库中的parse模块,定义了处理URL的标准接口,例如实现URL各部分的抽取、合并以及链接转换。它支持如下协议的URL处理:file、ftp、gopher、hdl、http、https、imap、mailto、mms、news、prospero、rsync、rtsp、rtspu、sftp、sip、sips、snews、svn、svn+shh、telnet、wais。

1. urlparse( )

urlparse( )方法可以实现URL的识别和分段。API用法如下:

urllib.parse.urlparse(urlstring,scheme='',allow_fragments=True)

其中,urlstring参数是必选项,其余都是可选的。

  • urlstring:待解析的URL。
  • scheme:默认的解析协议。如果待解析的URL中没有包含协议信息,会将scheme指定的协议作为默认的协议,只在URL中不包含scheme信息时才生效。
  • allow_fragments:是否允许解析fragment,默认值为True,如果为False,则fragment部分会被忽略,它会被解析为path、param或者query的一部分,而fragment部分为空。

urlparse( )方法的返回结果是一个ParseResult类型的对象,它包含6个部分,分别是scheme(协议)、netloc(域名)、path(访问路径)、params(参数)、query(查询条件,一般用作GET类型的URL)、fragment(锚点)。一般的URL都会由这6部分组成。

1)urlparse( )方法的基本使用,使用它解析一个URL。

from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html;user?id=5#comment')
print(type(result))
print(result)


2)如果指定了scheme参数,且URL中没有包含scheme参数时,则解析时使用scheme参数指定的协议。

from urllib.parse import urlparse
result = urlparse('www.baidu.com/index.html;user?id=5#comment',scheme='http')
print(result)


​ 由于URL中没有包含scheme,而通过scheme参数指定了协议,所以从运行结果可以看出,解析时使用的是scheme指定的协议,但由 于URL中未指定scheme,所以解析的netloc为空。

3) 如果URL中包含了scheme,而同时又指定了scheme参数,则解析时默认使用URL中的scheme。

from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html;user?id=5#comment',scheme='https')
print(result)


​ 从运行结果可以看出,解析时使用的是URL中的scheme。

4)如果allow_fragments值为False,则URL中包含的fragment将会被解析为path、params或者query的一部分。

from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html;user?id=5#comment',allow_fragments=False)
print(result)


​ 可以看出,fragment被解析为了query的一部分,而fragment为空。如果URL中不包含params和query:

from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html;user?id=5#comment',allow_fragments=False)
print(result)


​ 可以看出,当URL中不包含params和query时,fragment被解析为了path的一部分,而fragment为空。

5)urlparse( )的返回结果ParseResult实际上是一个元组,我们可以用索引顺序来获取,也可以用属性名获取。

from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html#comment',allow_fragments=False)
#打印:http http www.baidu.com www.baidu.com
print(result.scheme,result[0],result.netloc,result[1])

2. urlunparse( )

与urlparse( )对立的方法是urlunparse( ),它用于构造一个URL,接收的参数是一个可迭代的对象(如列表、元组等),长度必须是6,否则会抛出参数数量不足或者过多的问题。

from urllib.parse import urlunparse
data = ['http','www.baidu.com','index.html','user','a=6','comment']
#打印:http://www.baidu.com/index.html;user?a=6#comment
print(urlunparse(data));

3. urlsplit( )

urlsplit( )方法与urlparse( )方法类似,只不过urlsplit( )方法不单独解析params部分,而是将其解析到path部分中。

from urllib.parse import urlsplit
result = urlsplit('http://www.baidu.com/index.html;user?id=5#comment')
#打印:SplitResult(scheme='http', netloc='www.baidu.com', path='/index.html;user', query='id=5', fragment='comment')
print(result)

它返回的是SplitResult类型的对象,其实是一个元组类型,所以既可以用属性获取值,也可以用索引来获取。

from urllib.parse import urlsplit
result = urlsplit('http://www.baidu.com/index.html;user?id=5#comment')
#打印:http
print(result.scheme)
#打印:http
print(result[0])

4. urlunsplit( )

与urlsplit( )对立的方法是urlunsplit( ),它用于构造一个URL,接收的参数是一个可迭代的对象(如列表、元组等),长度必须是5,否则会抛出参数数量不足或者过多的问题。

from urllib.parse import urlunsplit
data = ['http','www.baidu.com','index.html','a=6','comment']
#打印:http://www.baidu.com/index.html?a=6#comment
print(urlunsplit(data))

5. urljoin( )

除了使用urlunparse( )和urlunsplit( )方法可以构造URL,还可以通过urljoin( )方法构造URL。使用urljoin( )方法时,提供一个base_url(基础URL)作为第一个参数,将新的URL作为第二个参数,该方法会分析base_url中的scheme、netloc和path这3个内容并对新的URL缺失的部分进行补充,最后补充后的URL。

from urllib.parse import urljoin
print(urljoin('http://www.baidu.com','FAQ.html'))
print(urljoin('http://www.baidu.com','https://cuiqingcai.com/FAQ.html'))
print(urljoin('http://www.baidu.com/about.html','https://cuiqingcai.com/FAQ.html'))
print(urljoin('http://www.baidu.com/about.html','https://cuiqingcai.com/FAQ.html?question=2'))
print(urljoin('http://www.baidu.com/about.html','https://cuiqingcai.com/index.php'))
print(urljoin('http://www.baidu.com','?category=2#comment'))
print(urljoin('www.baidu.com','?category=2#comment'))
print(urljoin('www.baidu.com#comment','?category=2'))


可以发现,base_url提供了三项内容scheme、netloc、path,如果这3项在新的URL中不存在,就予以补充;如果新的URL中已存在,不做替换。而base_url中的params、query、fragment是不起作用的。


6. urlencode( )

urlencode( )方法在构造请求参数时使用。

1)在GET请求方式中构造请求参数。

from urllib.parse import urlencode
params = {
	'name':'germey',
	'age':22
}
base_url = 'http://www.baidu.com?'
url = base_url+urlencode(params)
#打印:http://www.baidu.com?name=germey&age=22
print(url)

2)在POST请求方式中构造请求参数。

import urllib.request
from urllib.parse import urlencode
params = {
  'name':'germey',
  'age':22
}
data = bytes(urlencode(params),encoding='utf-8')
response = urllib.request.urlopen('http://httpbin.org/post',data=data)
print(response.read())

7. parse_qs( )

parse_qs( )方法可以将代表参数的字符串转回为字典。

from urllib.parse import parse_qs
query = 'name=germey&age=22'
#打印:{'name': ['germey'], 'age': ['22']}
print(parse_qs(query))

8. parse_qsl( )

与parse_qs( )方法功能类似,将代表参数的字符串转换为元组组成的列表。

from urllib.parse import parse_qsl
query = 'name=germey&age=22'
#打印:[('name', 'germey'), ('age', '22')]
print(parse_qsl(query))

返回结果是一个列表,列表中每一个元素都是一个元组,元组的第一个内容是参数名,第二个内容是参数值。


9. quote( )

quote( )方法可以将内容转换为URL编码的格式。当URL中带有中文参数时,会导致乱码问题,此时可以用quote( )方法将其转换为URL编码。

from urllib.parse import quote
keyword = '你好'
url = 'https://www.baidu.com/s?wd='+quote(keyword)
#打印:https://www.baidu.com/s?wd=%E4%BD%A0%E5%A5%BD
print(url)

10. unquote( )

unquote( )与quote( )方法对应,可以对URL编码的字符串进行解码。

from urllib.parse import unquote
url = 'https://www.baidu.com/s?wd=%E4%BD%A0%E5%A5%BD'
#打印:https://www.baidu.com/s?wd=你好
print(unquote(url))



robotparser模块

利用urllib库中的robotparser模块,可以实现对网站Robots协议的分析。

1. Robots协议

Robots协议也称作爬虫协议、机器人协议,它的全名叫做网络爬虫排除标准(Robots Exclusion Protocol),用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些页面不可以抓取。它通常是一个名为robots.txt的文本文件,一般放在网站的根目录下。当搜索爬虫访问一个站点时,它首先会检查这个站点根目录下是否存在robots.txt文件,如果存在,搜索爬虫会根据其中定义的爬取范围来爬取;如果没有找到这个文件,搜索爬虫便会访问所有可直接访问的页面。

1)robots.txt文件样例1。所有爬虫都不可以爬取任何页面,但public目录可以爬取。

User-agent:*
Disallow:/
Allow:/public/
  • User-agent:描述了搜索爬虫的名称,*则表示该协议对所有爬虫有效。比如User-agent:Baiduspider表示对百度爬虫是有效的。如果有多条User-agent记录,就会有多个爬虫会受到爬取限制,但至少需要指定一条。
  • Disallow:指定不允许爬取的目录,/表示所有页面都不允许爬取。
  • Allow:一般和Disallow一起使用,不会单独使用,用来排除Disallow指定的规则,指定除了Disallow指定的页面外,哪些页面可以抓取。

2)robots.txt文件样例2。 禁止爬虫爬取任何目录。

User-agent:*
Disallow:/

3)robots.txt文件样例3。 允许爬虫爬取任何页面。

User-agent:*
Disallow:

4)robots.txt文件样例。只允许名称为WebCrawler的爬虫爬取任何页面,不允许其他爬虫爬取任何页面。

User-agent:WebCrawler
Disallow:
User-agent:*
Disallow:/

2. 爬虫名称

爬虫是有名称的,常见的搜索爬虫的名称及对应的网站。

爬虫名称所属网站
BaiduSpider百度www.baidu.com
Googlebot谷歌www.google.com
360Spider360搜索www.so.com
Yodaobot有道www.youdao.com
ia_archiverAlexawww.alexa.cn
Scooteraltavistawww.altavista.com

3. robotparse模块的使用

robotparse模块提供了一个RobotFileParser类,该类可以根据网站的robots.txt文件来判断一个爬虫是否有权限来爬取这个网页。该类使用简单,只需要在构造方法里传入robots.txt的链接即可。

urllib.robotparser.RobotFileParser(url='')

url参数是可选的,如果在构造时没有传入url,最后通过set_url( )方法设置也是可以的。RobotFileParser类常用方法如下:

  • set_url( ):用于设置robots.txt文件的链接。如果在创建RobotFileParser对象时传入了url,那么就不需要再使用这个方法设置了。
  • read( ):读取robots.txt文件并进行分析。注意,该方法执行一个读取和分析操作,如果不调用这个方法,接下来的判断都会为False,所以一定记得调用这个方法,这个方法不会返回任何内容,但是执行了读取分析操作。
  • parse( ):用来解析robots.txt文件,传入的参数时robots.txt某些行的内容,它会按照robots.txt的语法规则来分析这些内容。
  • can_fetch( ):该方法接收两个参数,第一个是User-agent(爬虫名称),第二个是要抓取的URL;返回True或False,True表示允许该名称的爬虫可以爬取该URL,False表示不允许。
  • mtime( ):返回的是上次读取分析robots.txt的时间,这对于长时间分析和爬取的爬虫是很有必要的,你可能需要定期检查来读取分析最新的robots.txt。
  • modified( ):它同样对于长时间分析和爬取的爬虫很有帮助,将当前时间设置为上次爬取和分析robots.txt的时间。

1)判断简书某些网页是否可以爬取。

from urllib.robotparser import RobotFileParser
rp = RobotFileParser()
#设置robots.txt文件的路径
rp.set_url('https://www.jianshu.com/')
#执行读取分析操作
rp.read()
#判断是否可爬
print(rp.can_fetch('*','https://www.jianshu.com/p/b67554025d7d'))
print(rp.can_fetch('*','https://www.jianshu.com/search?q=python&page=1&type=collections'))

在这里插入图片描述
2)使用parse( )方法执行读取和分析操作。

from urllib.robotparser import RobotFileParser
from urllib.request import urlopen
rp = RobotFileParser()
#通过urlopen()直接打开百度的robots.txt文件并交给RobotFileParser进行分析
rp.parse(urlopen('https://www.baidu.com/robots.txt').read().decode('utf-8').split('\n'))
#判断是否可爬
print(rp.can_fetch('*','https://www.baidu.com/p/b67554025d7d'))
print(rp.can_fetch('*','https://www.baidu/search?q=python&page=1&type=collections'))

有些时候,判断是否可爬时返回False或者爬虫运行出现403拒绝服务现象,在发送请求时设置请求头中User-Agent和Host就可能返回True了。


Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐