《python3网络爬虫开发实战 第二版》之基本库的使用-urllib的使用 详解

news2024/9/27 23:34:14

文章目录

  • 1 urllib 库的使用
    • 1.1 request模块
      • 1.1.1 urlopen类
        • 1.1.1.1 最简单的爬虫-爬取百度首页
        • 1.1.1.2 urlopen方法的参数
          • 1.1.1.2.1 data参数
          • 1.1.1.2.2 timeout参数
          • 1.1.1.2.3 其他参数
      • 1.1.2 Request 类
      • 1.1.3 Handler
    • 1.2 error模块
      • 1.2.1 URLError 类
      • 1.2.2 HTTPError类
      • 1.2.3 比较好的捕获异常的方法
    • 1.3 parse模块
      • 1.3.1 urlparse()
        • 1.3.1.1 urlparse()的基本解析方式
        • 1.3.1.2 urlparse()的API
      • 1.3.2 urlunparse()
      • 1.3.3 urlsplit()
      • 1.3.4 urlunsplit()
      • 1.3.5 unjoin()
      • 1.3.6 urlencode()
      • 1.3.7 parses_qs()
      • 1.3.8 parse_qsl
      • 1.3.9 quote()
      • 1.3.10 unquote()
    • 1.4 robotparser模块
      • 1.4.1 Robots协议
        • 1.4.2 爬虫名称
        • 1.4.3 robotparser

1 urllib 库的使用

urllib库是python内置的HTTP请求库,可以实现HTTP请求的发送。有了urllib库,我们就无需深入到底层去了解到底是怎样传输和通信的。
使用urllib库,通过几行代码就可以完成一次请求和响应的处理过程

urllib库包含4个模块

  1. request模块:是最基本的HTTP请求模块,可以模拟请求的发送。
  2. error模块:异常处理模块,可以捕捉请求过程中出现的异常,并进行处理。
  3. parse模块:一个工具模块,提供了许多URL的处理方法,例如拆分、分解、合并等等。
  4. robotparser模块:主要是用来识别网站的robots.txt文件,判断哪些网站可以爬,哪些不可以爬,实际用的比较少。

1.1 request模块

使用urllib.request可以发送请求并得到响应。
urllib.request提供了最基本的构造HTTP请求的方法,利用这个模块可以模拟浏览器的请求发起过程,同时还具有处理授权验证(Authentication)、重定向(Redirection)、浏览器Cookie以及其他一些功能。

1.1.1 urlopen类

1.1.1.1 最简单的爬虫-爬取百度首页

以爬取百度首页为例,看一下如何使用request模块,爬取网页信息。
代码如下:

def urlopen_1():
    import urllib.request

    response = urllib.request.urlopen('https://www.baidu.com')
    print(response.read().decode('utf-8'))  # read()可以得到响应的网页的内容,并将其使用'utf-8'编码方式解码
    print(type(response))  # <class 'http.client.HTTPResponse'>
    print(response.status)  # 可以直接获得返回响应的状态码  200
    print(response.getheaders())  # 可以直接获取返回响应的全部头信息
    print(response.getheader('Server'))  # 获取响应头中的Server的值  BWS/1.1

print(response.read().decode('utf-8'))输出结果如下图所示,可以看出有完整的HTML页面结构,并且格式规整。
在这里插入图片描述
下图是print(response.read()打印输出的结果,可以看出,其中也是完整的HTML页面,但是存在许多的转义字符。因此如果想要得到页面的格式化输出,并且便于操作,我们需要对其进行解码。
在这里插入图片描述
print(type(response))的输出结果是:<class 'http.client.HTTPResponse'>
response的类型是HTTPResponse类型的对象,有很多的方法和属性。

下图是response.getheaders()序列化输出的结果,可以看出,是响应头中的全部信息。
在这里插入图片描述
response.getheaders('Server') 是获取响应头中Server的值,从上图中看出 应该返回BWS/1.1,实际运行代码,打印输出的也是一致的。

1.1.1.2 urlopen方法的参数

urlopen()的API如下:
urllib.request.urlopen(url, data=None,[timeout]*, cafile=None, capath=None, cadefault=False, context=None)
下面具体说明各个参数的用法

1.1.1.2.1 data参数

data参数是可选的。是用来传递POST方法中的表单的。
这个参数,需要使用bytes将表单信息转化为字节流编码格式的内容。
一旦使用了这个参数,这个请求方法就是POST

bytes(str, encoding) 第一个参数是字符串,第二个参数是采用何种编码方式编码成bytes类型
由于我们在提交表单时,以键值对(字典)的方式较多,因此还需要通过urllib.parse模块中的urlencode方法将字典参数转化为字符串。

以测试网站上提交POST请求为例,代码如下:

def urlopen_post():
    import urllib.request
    import urllib.parse
    data = bytes(urllib.parse.urlencode({'name': 'this is a test', 'code': 300}), encoding='utf-8')
    response = urllib.request.urlopen('https://www.httpbin.org/post', data=data)
    print(response.read().decode('utf-8'))

代码执行的结果如下图所示:
可以看出我们传递的参数在form参数中进行显示,也就是我们的参数data实质上是提交的表单信息
在这里插入图片描述

1.1.1.2.2 timeout参数

timeout参数是用来设置超时时间的。如果在设置时长内没有得到回应信息,就会报网络错误。
为了显示效果,将时间设置为0.01s,但是在实际爬虫过程中,一般设置为3-5s

以请求百度首页为例,设置超时时间为0.01s
代码如下:

def urlopen_timeout():
    import urllib.request
    response = urllib.request.urlopen('https://www.baidu.com', timeout=0.01)
    print(response.read())

代码运行的结果如下图所示:
在这里插入图片描述> 从上图可以看出,超时是urllib.error.URLError类型的错误。
因此我们可以对urllib.error.URLError进行try...except..捕捉,并输出响应的提示信息。
代码如下:

def urlopen_timeout():
    import urllib.request
    import urllib.error
    try:
        response = urllib.request.urlopen('https://www.baidu.com', timeout=0.01)
        print(response.read())
    except urllib.error.URLError as e:
        print('TIME OUT')

代码执行的结果如下图所示:
在这里插入图片描述

1.1.1.2.3 其他参数

urlopen除了data参数、timeout参数,urlopen还有contextcafilecapathcadefault
context:是用来指定SSL的设置,该参数必须是ssl.SSLContext
cafile:用来指定CA,在请求HTTPS链接时用
capath:用来指定CA证书的路径,在请求HTTPS链接时用
cadefault:已经弃用,默认是False

1.1.2 Request 类

当我们需要在请求中加入Headers等信息的时候,就需要Request类来构建请求体。
我们在发送请求时,还是通过urlopen来进行请求
urlopen方法的第一个url参数,不再传入一个url链接,而是传入一个Request类型的对象

Request类型的对象构造方法如下:
urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
url:用于请求的URL,这个参数是必传参数
data:同urlopen中的data一样,需要传入bytes类型数据,如果是数据是字典,需要先编码再转。
headers:是一个字典,是请求头。经常在里面添加User-Agent来伪装浏览器
origin_req_host:用来指定请求方的host名称或者IP地址
unverifiable:表示请求是否是无法验证的,默认取值是False
method:表示请求使用的方法,如GETPOSTPUT。这个参数是字符串。

以测试网站为例,构建Request类,发送POST请求。
代码如下:

def request_class():
    import urllib.request
    import urllib.parse
    url = 'https://www.httpbin.org/post'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
        'Host': 'www.httpbin.org'
    }
    dict = {'name': 'this is a test', 'code': 300}
    data = bytes(urllib.parse.urlencode(dict), encoding='utf-8')
    request = urllib.request.Request(url=url, data=data, headers=headers, method='POST')
    response = urllib.request.urlopen(request)
    print(response.read().decode('utf-8'))

代码运行的结果如下图所示:
通过观察输出的formRequest对象中我们传入的参数data一致,可以知道Request对象中我们传入的参数data是表单数据,用法和效果与urlopendata一样。
在这里插入图片描述

1.1.3 Handler

Handler可以理解为各种处理器,有专门处理登录验证的、处理Cookie的,处理代理设置的。
利用这个Handler,我们几乎可以实现HTTP请求中所有的功能

urllib.request模块里有一个BaseHandler类,这是所有Handler类的父类。
提供了最基本的方法,例如default_openprotocol_request

会有各种Handler子类继承BaseHandler

  • HTTPDefaultErrorHandler :用于处理HTTP响应错误,所有的错误都会抛出HTTPError类型的异常
  • HTTPRedirectHandler:用于处理重定向
  • HTTPCookieProcessor :用于处理Cookie
  • ProxyHandler :用于设置代理,默认是空
  • HTTPPasswordMgr :用于管理密码,维护着用户名密码的对照表
  • HTTPBasicAuthHandler :用于管理认证。

比较重要的类除了BaseHandler之外,还有一个OpenerDirector ,我们称之为Opener
我们使用的urlopen就是urllib库提供的一种Opener
当需要实现更高级的功能,深入一层进行配置时,就使用到了Opener

1.2 error模块

urllib库中的error模块定义了由request模块产生的异常。
当出现问题时,request模块便会抛出error模块中定义的异常

Error模块中常用的类有:

  • URLError:继承自OSError,是error异常模块的基类
  • HTTPError:是URLError的子类,专门处理HTTP请求错误,如认证请求失败等

1.2.1 URLError 类

URLError 类来自urllib库的error模块,继承自OSError
error异常模块的基类,
request模块产生的异常都可以通过捕获这个类来处理

URLError有一个属性是reason
可以在捕获到这个异常时,对异常处理,并打印其reason。
这样就可以防止因为报错而终止运行

以超时为例,捕捉异常,并打印原因
代码如下:

def error_except():
    import urllib.request
    import urllib.error
    try:
        request = urllib.request.urlopen('https://www.baidu.com', timeout=0.001)
        print(request.read().decode('utf-8'))
    except urllib.error.URLError as e:
        print(type(e.reason))
        print(e.reason)

代码执行的结果如下图所示:
程序没有直接报错,而是输出了错误原因,这样就可以避免程序异常终止,同时异常得到了有效处理。
在这里插入图片描述

reason属性返回的不一定是字符串也可能是一个对象
上述代码中打印的type(e.reason),其输出结果是 TimeoutError
因此我们可以使用isinstance方法来判断其类型

改进后的代码如下:

def error_except_urlerror():
    import urllib.request
    import urllib.error
    try:
        request = urllib.request.urlopen('https://www.baidu.com', timeout=0.001)
        print(request.read().decode('utf-8'))
    except urllib.error.URLError as e:
        # print(type(e.reason))  # <class 'TimeoutError'>
        # print(e.reason)
        if isinstance(e.reason, TimeoutError):
            print('TIME OUT')

代码执行的结果如下图所示:
只是输出了‘TIME OUT’

在这里插入图片描述

1.2.2 HTTPError类

HTTPError类是URLError类的子类,是专门用来处理HTTP请求错误的类

HTTPError类有三个属性

  • reason :同父类一样,用于返回错误的原因
  • code:返回HTTP状态码
  • headers: 返回请求头

以打开一个不存在的网页为例,对异常进行捕获
并输出其code、reason、headers
代码如下:

def error_except_httperror():
    import urllib.request
    import urllib.error
    try:
        request = urllib.request.urlopen('https://www.baidu.com/bucunzai')
        print(request.read().decode('utf-8'))
    except urllib.error.HTTPError as e:
        print(e.code, e.reason, e.headers, sep='\n')

代码执行的结果如下:

在这里插入图片描述

1.2.3 比较好的捕获异常的方法

由于URLErrorHTTPError的父类,因此可以选择先捕获子类的错误,再捕获父类的错误。

对上述代码进行修改,修改后的代码如下:

def error_except_all():
    import urllib.request
    import urllib.error
    try:
        request = urllib.request.urlopen('https://www.baidu.com/bucunzai')
        print(request.read().decode('utf-8'))
    except urllib.error.HTTPError as e:
        print(e.code, e.reason, e.headers, sep='\n')
    except urllib.error.URLError as e:
        print(e.reason)
    else:
        print('successful ')

修改后的代码 可以先捕获HTTPError,获取其错误原因、状态码、请求头等信息
如果不是HTTPError ,就会捕获URLError,输出错误原因
最后使用else来处理正常的逻辑。

修改后的代码执行的效果同上。

1.3 parse模块

前文在传递data参数的时候,使用urllib.parse模块对字典进行格式转换
urllib.parse模块定义了处理URL的标准接口,
例如:实现URL各部分的抽取、合并以及链接转换
parse 支持大部分协议的URL处理

parse中常用的方法有:

  • urlparse:可以实现URL的识别和分段
  • urlunparse:将接收到的参数构造为一个链接,其参数是一个可迭代对象,其长度必须为6
  • urlsplit:可以实现URL的识别和分段,只返回5个结果。
  • urlunsplit:将链接各个部分组合成完整链接的方法,其参数是一个可迭代对象,参数长度为5
  • urljoin:是生成链接的一种方法,并且没有长度要求
  • urlencode:将字典类型的请求参数转化为GET请求参数
  • parse_qs:将一串GET请求参数转回字典类型
  • parse_qsl:将参数转化为由元组组成的列表
  • quote:可以将内容转化为URL编码的格式,尤其是URL中带有中文参数的时候
  • unquote:可以进行URL解码,

1.3.1 urlparse()

urlparse()可以实现URL的识别和分段

1.3.1.1 urlparse()的基本解析方式

使用urlparse对网址进行解析
代码如下:

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

代码执行的结果如下图所示:

在这里插入图片描述

从输出的结果可以看到:
解析的结果是一个RarseResult类型的对象,包含6部分:schemenetlocpathparamsqueryfragment

对照实例中的URL可以发现:

  • //前面的内容就是scheme,代表是协议
  • 第一个/符号前面的是netloc , 代表域名
  • 后面是path,代表访问路径
  • 分号‘;’后面是params,代表参数
  • 问号‘?’后面是查询条件query,一般用作GET类型的URL
  • 井号‘#’后面是锚点fragment,用于直接定位页面内部的下拉位置
    将上述合并在一起可以得到一个标准的URL格式
    scheme://netloc/path;params?query#fragment

1.3.1.2 urlparse()的API

urlparse()的API如下:
urlparse(urlstring, scheme=' ',allow_fragments=True)
urlparse()有三个参数

  • urlstring:这是必填项,是待解析的URL
  • scheme:这是默认的协议,如果待解析的URL没有带协议信息,就会将这个作为默认协议
  • allow_fragments:是否忽略fragment。如果此项被设置为False,那么fragment部分就会被解析为path、params或者query的一部分,而fragment部分为空

urlparse()返回的ParseResult实际上是一个元组,
可以通过其属性名获取其内容,
也可以使用索引来顺序获取

代码如下:

def urlparse_senior():
    from urllib.parse import urlparse
    url = 'www.baidu.com/index.html;user?id=5#comment'
    result = urlparse(url, scheme='https', allow_fragments=False)
    print(result)
    print('通过属性名获取:', result.path, sep='\t')
    print('通过索引获取:', result[4], sep='\t')

代码执行的结果如下图所示:

在这里插入图片描述

1.3.2 urlunparse()

urlunparse()用于构造URL,
其参数是一个可迭代对象,如:列表、元组、或者特定的数据结构
其参数的长度必须是6,否则会抛出参数数量不足或或多的问题

分别定义三个列表:一个长度为6,一个长度为7,一个长度为5,
对正常的结果进行输出,对异常进行捕捉。
代码如下:

def urlunparse_test():
    from urllib.parse import urlunparse
    data_normal = ['https', 'www.baidu.com/index.html', 'user', 'id=5', 'comment']
    data_over = ['https', 'www.baidu.com/index.html', 'user', 'id=5', 'comment', 'duoyige']
    data_less = ['https', 'www.baidu.com/index.html', 'user', 'id=5']
    try:

        result_normal = urlunparse(data_normal)
        print(result_normal)
        result_over = urlunparse(data_over)
        print(result_over)
    except ValueError as e:
        print(e)

        try:
            result_less = urlunparse(data_less)
            print(result_less)
        except ValueError as e:
            print(e)

代码执行的结果如下:
在这里插入图片描述

1.3.3 urlsplit()

urlsplit()urlparse()非常相似,
区别就是urlsplit()没有params这一部分,而是将params合到path中
只返回5个结果

其返回结果是SplitResult类型的对象
同样的 SplitResult也是一个元组,可以通过属性名获取值,也可以根据索引获取
其用法与urlparse()类似。

1.3.4 urlunsplit()

urlunsplit()urlunparse()类似,
区别在于 urlunsplit()传入的可迭代参数,其长度必须是5。
其用法同urlunparse()类似。

1.3.5 unjoin()

urlunparse()urlunsplit()都可以完成链接的合并,但是对其可迭代对象参数的长度有限制,链接的每一部分都要清楚的分开。

urljoin()也是一种生成链接的方法。
该方法有两个参数,第一个参数是基础链接base_url,第二个参数是新的链接
urljoin()会分析base_url中的schemeneltocpath三个部分的内容,并对新链接缺失的部分进行补充。

为便于理解,代码如下:

def urljoin_test():
    from urllib.parse import urljoin
    print('1. 这个新链接没有scheme、netloc: ',
          urljoin('https://www.baidu.com', 'newpage.html'), sep='\t')
    print('2. 这个新链接什么都不缺,基础链接没有path: ',
          urljoin('https://www.baidu.com', 'https://newlink/newpage.html'), sep='\t')
    print('3. 这个新链接和基础链接什么都不缺: ',
          urljoin('https://www.baidu.com/base.html', 'https://newlink/newpage.html'), sep='\t')
    print('4. 这个基础链接什么都不缺,新链接多了一个query: ',
          urljoin('https://www.baidu.com/base.html', 'https://newlink/newpage.html?query=2'), sep='\t')
    print('5. 这个基础链接少了path,多了一个query,新链接什么都不缺: ',
          urljoin('https://www.baidu.com?query=1', 'https://newlink/newpage.html'), sep='\t')
    print('6. 这个基础链接少了path;新链接多了query、fragment,少了scheme、netloc、path: ',
          urljoin('https://www.baidu.com', '?query=2#comment'), sep='\t')
    print('7. 这个基础链接没有scheme、path;新链接多了query、fragment,少了scheme、netloc、path: ',
          urljoin('https://www.baidu.com/base.html', '?query=2#comment'), sep='\t')
    print('8. 这个基础链接没有scheme、path,多了fragment;新链接多了query,少了scheme、netloc、path: ',
          urljoin('https://www.baidu.com#comment', '?query=2'), sep='\t')

运行的结果如下图所示:
在这里插入图片描述

可以发现 base_url提供了 scheme、netloc和path
如果新链接里面不存在这三项,就用base_url中的进行补充,否则,就使用新链接的

1.3.6 urlencode()

可以理解为将字典的参数序列化为链接中的一部分
在构造GET参数的时候很有用

代码如下:


def urlencode_test():
    from urllib.parse import urlencode

    data = {'name': 'getcanshu', 'type': 'dict'}
    baseurl = 'https://www.baidu.com?'
    url = baseurl + urlencode(data)
    print(url)

代码执行结果如下图所示:
在这里插入图片描述

1.3.7 parses_qs()

parse_qs()就是反序列化,
将GET请求参数转回字典

代码如下:

def parse_qs_test():
    from urllib.parse import parse_qs
    print(parse_qs('name=getcanshu&type=dict'))

运行结果如下图所示:
在这里插入图片描述

1.3.8 parse_qsl

parse_qsl()将参数转化为由元组组成的列表
代码如下:

def parse_qsl_test():
    from urllib.parse import parse_qsl
    print(parse_qsl('name=getcanshu&type=dict'))

运行结果如下:
可以看出结果是一个列表,列表中每一个元素都是元组,
元组的第一个是参数名,后面的是参数值

在这里插入图片描述

1.3.9 quote()

quote()可以将内容转化为URL编码的格式
当URL中带有中文参数时,有可能会导致乱码问题,
此时可以使用quote()将中文字符转化为URL编码

实例如下:

def quote_test():
    from urllib.parse import quote
    key = '测试中文参数'
    url = 'https://www.baicu.com/s?wd=' + quote(key)
    print(url)

运行的结果如下图所示

在这里插入图片描述

1.3.10 unquote()

unquote()quote()的逆操作,
可以进行URL解码

实例如下:

def unquote_test():
    from urllib.parse import unquote
    print(unquote('https://www.baicu.com/s?wd=%E6%B5%8B%E8%AF%95%E4%B8%AD%E6%96%87%E5%8F%82%E6%95%B0'))

运行的结果如下图所示:
在这里插入图片描述

1.4 robotparser模块

robotparser模块可以分析网站的Robots协议

1.4.1 Robots协议

Robots协议 也称为爬虫协议、机器人协议。全名为网络爬虫排除标准
是用来告诉爬虫和搜索引擎哪些页面课可以抓取,哪些不可以。
通常是一个叫做robots.txt文件,一般放在网站的根目录下

搜索爬虫在访问一个站点时,首先会检查这个站点根目录下是否存在robots.txt文件
如果存在,就会根据其中定义的爬取范围来爬取。
如果没有找到这个文件,搜索爬虫就会访问所有可直接访问的页面

robots.txt样例如下:

User-agent: *
Disallow: /
Allow: /public/

User-agent描述搜索爬虫的名称,设置为* ,代表Robots协议对所有爬虫都有效
如果设置为User-agent: Baiduspider
这代表设置的规则对百度爬虫是有效的。
如果有多条 User-agent记录,意味着有多个爬虫会受到爬取限制
但是至少要指定一条

Disallow 指定了不允许爬虫爬取的目录
设置为 / 代表不允许爬取所有页面

Allow 一般不会单独使用,会和Disallow一起使用,用来排除某些限制,
上例中Allow设置为/public/,结合Disallow的设置,
表示所有的页面都不可以进行爬取,但是可以爬取public目录。

1.4.2 爬虫名称

User-Agent 中设置的是爬虫名称,爬虫名称是什么?
爬虫时有固定名字的,

常见搜索爬虫的名称及对应得网站如下表所示

爬虫名称网站名称
BaiduSpider百度
Googlebot谷歌
360Spider360搜索
YoudaoBot有道
is_archiverAlexa
Scooteraltavista
Bingbot必应

1.4.3 robotparser

robotparser提供了一个类RobotFileParser
它可以根据某网站的robots.txt文件判断一个爬虫是否有权限爬取这个网页
该类的用法很简单,只需要在构造方法里传入robots.txt文件的链接即可。
当然可以不在声明时传入robots.txt文件的链接,让其默认为空,后面再使用set_url()进行设置。

RobotFileParser类常用的方法:

  • set_url():用来设置robots.txt文件的链接,当然如果在创建RobotFileParser对象时传入了链接,就不需要进行设置了。
  • read():读取robots.txt文件并进行分析。如果不调用这个方法,后面的判断都会为False
  • parse():用来解析robots.txt文件,传入的参数是robots.txt文件中某些行的内容,会按照robots.txt的语法规则来分析这些内容。
  • can_fetch():有两个参数,第一个是User-Agent,第二个参数是要抓取的URL,返回的结果是布尔类型。表示User-Agent指示的搜索引擎是否可以抓取这个URL。
  • mtime():返回上次抓取和分析robots.txt文件的时间,对于长时间分析和抓取robots.txt文件的搜索爬虫来说,可能需要定期检查以抓取最新的robots.txt文件。
  • modified():同样对长时间分析和抓取的搜索爬虫很有帮助,可以将当前时间设置为上次抓取和分析robots.txt文件的时间。

以百度为例,使用BaiduSpiderGooglebot爬取百度的homepage页面和百度的首页。
代码如下:

def robot_parser():
    from urllib.robotparser import RobotFileParser
    rp = RobotFileParser('https://www.baidu.com/robots.txt')   # 创建一个RobotFileParser对象实例
    rp.read()  # 读取和分析robots.txt文件
    base_url = 'https://www.baidu.com'
    homepage_url = base_url + '/homepage/'
    print(rp.can_fetch('Baiduspider', base_url))  # 判断能否通过Baiduspider 爬取百度首页
    print(rp.can_fetch('Googlebot', base_url))  # 判断能否通过Googlebot 爬取百度homepage页面
    print(rp.can_fetch('Baiduspider', homepage_url))  # 判断能否通过Baiduspider 爬取百度homepage页面
    print(rp.can_fetch('Googlebot', homepage_url))  # 判断能否通过Baiduspider 爬取百度homepage页面

运行的结果如下图所示

在这里插入图片描述

从运行结果可以看出,不能通过Googlebot爬取homepage页面。
打开百度的robots.txt,可以看到如下信息

在这里插入图片描述

从上图可以看出,百度的robot.txt文件没有限制Baiduspider对百度homepage页面的抓取
但是限制了Googlebothomepage页面的抓取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/349690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式-分布式服务

微服务API 网关 网关的概念来源于计算机网络&#xff0c;表示不同网络之间的关口。在系统设计中&#xff0c;网关也是一个重要的角色&#xff0c;其中最典型的是各大公司的开放平台&#xff0c;开放平台类网关是企业内部系统对外的统一入口&#xff0c;承担了很多业务&#xf…

【Java】虚拟机JVM

一、运行时数据区域 程序计数器 记录正在执行的虚拟机字节码指令的地址&#xff08;如果正在执行的是本地方法则为空&#xff09; Java虚拟机栈 每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程&am…

Mysql数据库的时间(3)一如何用函数插入时间

暂时用下面四个日期函数插入时间 如:insert into Stu(time) values (now()); Mysql的时间函数描述对应的Mysql的时间类型now()/sysdate()NOW()函数以YYYY-MM-DD HH:MM:SS返回当前的日期时间date/time/dateTime/timeStamp/yearcurDate()/current_date()返回当前的日期YYYY-M…

计算机网络笔记(三)—— 数据链路层

数据链路层概述 数据链路层以帧为单位传输数据。 封装成帧&#xff1a;给网络层提供的协议数据单元添加帧头帧尾 差错检测&#xff1a;检错码封装在帧尾 可靠传输&#xff1a;尽管误码不能避免&#xff0c;但如果可以实现发送什么就接受什么&#xff0c;就叫可靠传输 封装成…

RTOS随笔之FreeRTOS启动与同步方法

RTOS启动与同步机制RTOS启动任务切换场景任务同步机制队列信号量事件组任务通知任务延时RTOS启动 FreeRTOS在任务创建完成后调用函数vTaskStartScheduler()启动任务调度器。 vTaskStartScheduler()任务启动函数详解 void vTaskStartScheduler( void ) {BaseType_t xReturn;xR…

项目管理工具dhtmlxGantt甘特图入门教程(九):支持哪些数据格式(下篇)

这篇文章给大家讲解 dhtmlxGantt可以加载或支持哪些数据格式。 dhtmlxGantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表&#xff0c;可满足应用程序的所有需求&#xff0c;是最完善的甘特图图表库 DhtmlxGantt正版试用下载&#xff08;qun&#xff1a;764148812&am…

虚拟机NAT模式无法连外网

虚拟机使用NAT模式连接外网设置时要注意两点 虚拟机的网段要与物理机保持一致各个节点的IP中的GATEWAY要与虚拟机的网关保持一致 1、虚拟机的网段要与物理机保持一致 1.1首先查看物理机的ip&#xff0c;看虚拟机和物理机ip是否在同一网段 winR cmd计入控制台&#xff0c;然…

uni-app前端H5页面底部内容被tabbar遮挡

如果你想在原生 tabbar 上方悬浮一个菜单&#xff0c;之前写 bottom:0。这样的写法编译到 h5 后&#xff0c;这个菜单会和 tabbar 重叠&#xff0c;位于屏幕底部。 原码&#xff1a; <view style"position: fixed;bottom:0;left: 0;background-color: #007AFF;right: …

PythonWeb Django PostgreSQL创建Web项目(二)

安装数据库PostgreSQL并创建数据库 我第一次尝试使用PostgreSQL数据库&#xff0c;why&#xff1f;我喜欢它提供的丰富的数据类型&#xff0c;例如货币类型、枚举类型、几何类型(点、直线、线段、矩形等等)、网络地址类型、文本搜索类型、XML类型JSON类型等等&#xff0c;非常…

Web3中文|聊聊这个让Opensea头疼的新对手Blur ($BLUR)

2022年10月19日&#xff0c;NFT市场迎来一个新的平台。 这个被精心设计的NFT交易市场和聚合器被命名为Blur。 与其他NFT平台不同&#xff0c;Blur旨在提升专业交易者的NFT交易体验。它的开发团队认为其他交易平台存在界面混杂、无法获取分析数据和工具、处理速度缓慢等问题。…

postman使用简介

1、介绍 postman是一款功能强大的网页调试和模拟发送HTTP请求的Chrome插件&#xff0c;支持几乎所有类型的HTTP请求 2、下载及安装 官方文档&#xff1a;https://www.getpostman.com/docs/v6/ chrome插件&#xff1a;chrome浏览器应用商店直接搜索添加即可&#xff08;需墙&…

在魔改PLUS-F5280开发板上使用合封qsp iflash

文章目录引言硬件调整软件调整总结引言 由于目前灵动官网暂未发布正式版的PLUS-F5280开发板&#xff0c;可以使用现有的PLUS-F5270 v1.2开发板&#xff08;下文简称PLUS-F5270开发版&#xff09;替换为MM32F5280微控制器芯片&#xff0c;改装为PLUS-F5280开发板。本文记录了使…

【Mybatis源码解析】mapper实例化及执行流程源码分析

文章目录简介环境搭建源码解析基础环境&#xff1a;JDK17、SpringBoot3.0、mysql5.7 储备知识&#xff1a;《【Spring6源码・AOP】AOP源码解析》、《JDBC详细全解》 简介 基于SpringBoot的Mybatis源码解析&#xff1a; 1.如何对mapper实例化bean 在加载BeanDefinition时&a…

哈希表题目:矩阵置零

文章目录题目标题和出处难度题目描述要求示例数据范围进阶解法一思路和算法代码复杂度分析解法二思路和算法代码复杂度分析解法三思路和算法代码复杂度分析题目 标题和出处 标题&#xff1a;矩阵置零 出处&#xff1a;73. 矩阵置零 难度 3 级 题目描述 要求 给定一个 m…

oracle单库重建undo表空间步骤

前言&#xff1a;undo表空间不足可直接增加空间&#xff1b; alter tablespace UNDOTBS1 add datafile /data/oradata/datafile/UNDOTBS102.dbf size 30g autoextend off; 注&#xff1a;单次增加最大不得超过32G 回收空间 缩小表空间直接可以resize命令缩小&#xff1b…

webpack(高级)--创建自己的loader 同步loader 异步loader loader参数校验

webpack 创建自己的loader loader是用于对模块的源代码进行转换&#xff08;处理&#xff09; 我们使用过很多loader 比如css-loader style-loader babel-loader 我么如果想要自己创建一个loader 首先创建webpack环境 pnpm add webpack webpack-cli -D 之后创建loader模块…

Hadoop初步理解

产生原因 在之前&#xff0c;数据量小&#xff0c;增长速度慢&#xff0c;且数据基本都是文件。储存和处理这些数据并不麻烦&#xff0c;单个存储单元和处理器组合就可以。 之后随着互联网发展&#xff0c;产生了大量多种形式的数据。 非结构化数据&#xff1a;邮件、图像、音…

盘点3个.Net开发的WMS仓库管理系统

更多开源项目请查看&#xff1a;一个专注推荐.Net开源项目的榜单 仓库管理系统在企业中&#xff0c;重要性越来越高&#xff0c;不仅可以提高效率&#xff0c;还能降低企业的压力&#xff0c;企业通过协调和优化资源使用和物料流动&#xff0c;能极大程度地提升了管理效率&…

中国500强|长虹控股集团携手契约锁,推动采购-人事业务电子签

四川长虹电子控股集团&#xff08;以下简称“长虹控股集团”&#xff09;是国内知名的电器制造商之一&#xff0c;拥有六家上市公司、一家新三板的公众公司&#xff0c;入选世界品牌500强、中国企业家协会发布的中国500强企业榜单。此次&#xff0c;长虹控股集团携手契约锁打造…

数据分析与SAS学习笔记3

SAS在最新的展示图&#xff0c;表现力比较丰富。 SAS的处理流程&#xff1a; 数据步 过程步&#xff1a; ETL是数据分析非常重要的步骤。70%-90%花在收集数据以及整理数据&#xff0c;数据分析数据的时间不是很多的。 一个完整的数据步和过程步&#xff1a; 数据步基本语句总…