首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python3爬虫urllib

python3爬虫urllib

作者头像
AngelNH
发布2020-05-25 16:04:21
1.2K0
发布2020-05-25 16:04:21
举报
文章被收录于专栏:AngelNIAngelNI

基本库 urllib 的使用

urllib 简介

在 Python 中有两种方式可以发送 HTTP 请求,分别是自带的 urllib 库和第三方的 requests 库。

urllib 库:Python 内置的 HTTP 请求库,无需额外安装即可使用;Python 2 中有 urllib 和 urllib2 两个库来实现请求的发送,Python 3 中统一为 urllib。官方文档:https://docs.python.org/3/library/urllib.html

urllib所包含的常用模块

  1. urllib.request:模拟发送请求;
  2. urllib.error:异常处理模块,用于捕获异常;
  3. urrllib.parse:解析、拆分、合并URL
  4. urllib.robotparser:读取网站的robots.txt文件,判断哪些内容可以爬取

urllib.request所包含的常用方法

  1. urllib.request.urlopen():打开网址URL,这可以是一个字符串或一个 Request对象;
  2. urllib.request.Request():在请求的时候传入一些 headers 等信息;
  3. urllib.request.urlretrieve():将获取的URL的内容写到文件目录中去。

urllib.request所包含的常用方法

  1. URLError:继承自 OSError 类,是 error 异常模块的基类,由 request 模块产生的异常都可以通过捕获这个类来处理。
  2. HTTPError:是 URLError 的子类,专门用来处理 HTTP 请求错误,比如认证请求失败等。

urllib.parse 所包含的常用方法

  1. urllib.parse.urlencode():将字典参数序列化为 GET 请求参数;
  2. urllib.parse.parse_qs():将 GET 请求参数反序列化转回字典;
  3. urllib.parse.parse_qsl():将参数转化为元组组成的列表;
  4. urllib.parse.urlparse():对 URL 进行分段(返回6个结果);
  5. urllib.parse.urlunparse():对 URL 进行组合(长度必须为6);
  6. urllib.parse.urlsplit():对 URL 进行分段(不单独解析params部分,返回5个结果);
  7. urllib.parse.urlunsplit():对 URL 进行组合(长度必须为5)
  8. urllib.parse.urljoin():对 URL 进行组合(没有长度限制,给定两个参数,自动分析 scheme、netloc 和 path 这 3 个内容并对新链接缺失的部分进行补充,最后返回结果);
  9. urllib.parse.quote():将内容转化为 URL 编码格式;
  10. urllib.parse.unquote():对 URL 进行解码。

urllib.robotparser 所包含的类

  1. RobotFileParser:根据网站的 robots.txt 文件来判断一个爬取爬虫是否有权限来爬取这个网页

urllib.request

urllib.request.urlopen()

基本使用方法

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

使用

import urllib.request 

response = urllib.request.urlopen('https://angelni.github.io/')
print(response)

输出响应对象的类型和属性:

import urllib.request 

response = urllib.request.urlopen('https://angelni.github.io/')
print(type(response))
print(response.status)
print(response.getheaders())
print(response.getheader('Server'))

运行结果

<class 'http.client.HTTPResponse'>
200
[('Connection', 'close'), ('Content-Length', '36930'), ('Content-Type', 'text/html; charset=utf-8'), ('Server', 'GitHub.com'), ('Strict-Transport-Security', 'max-age=rict-Transport-Security', 'max-age=31556952'), ('Last-Modified', 'Mon, 11 May 2020 05:38:18 GMT'), ('ETag', '"5eb8e4ca-9042"'), ('A('Expires', 'Thu, 21 May 2020 20:17ccess-Control-Allow-Origin', '*'), ('Expires', 'Thu, 21 May 2020 20:17:51 GMT'), ('Cache-Control', 'max-age=600'), ('X-Proxy-Cache', ('Accept-Ranges', 'bytes'), ('Dat, 'MISS'), ('X-GitHub-Request-Id', '9112:45A4:22C0FB:24F624:5EC6DF95'), ('Accept-Ranges', 'bytes'), ('Date', 'Fri, 22 May 2020 05:4IT'), ('X-Cache-Hits', '1'), ('X-Ti2:11 GMT'), ('Via', '1.1 varnish'), ('Age', '108'), ('X-Served-By', 'cache-tyo19939-TYO'), ('X-Cache', 'HIT'), ('X-Cache-Hits', '1'')]), ('X-Timer', 'S1590126131.497095,VS0,VE1'), ('Vary', 'Accept-Encoding'), ('X-Fastly-Request-ID', 'd0682d145390665c6ad5fa6b629b2af3a18a7654')]
GitHub.com
添加参数

timeout参数

timeout 设置为0.1,0.1秒过后服务器没有响应,便会抛出 URLError 异常

举例

import urllib.request

response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)  
print(response.read())
During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "f:\C-and-Python-Algorithn\python\Spider\1.py", line 3, in <module>
    response = urllib.request.urlopen('https://angelni.github.io/', timeout=0.1)  
  File "E:\python\lib\urllib\request.py", line 223, in urlopen
    return opener.open(url, data, timeout)
  File "E:\python\lib\urllib\request.py", line 526, in open
    response = self._open(req, data)
  File "E:\python\lib\urllib\request.py", line 544, in _open
    '_open', req)
  File "E:\python\lib\urllib\request.py", line 504, in _call_chain
    result = func(*args)
  File "E:\python\lib\urllib\request.py", line 1361, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "E:\python\lib\urllib\request.py", line 1320, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error _ssl.c:825: The handshake operation timed out>

urllib.request.Request()

Request() 方法可以在请求的时候传入一些 data、headers 等信息

Request() 的构造方法:

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

构造方法各个参数的解释:

  • url:用于请求 URL,这是必传参数,其他都是可选参数。
  • data:如果要传,必须传 bytes(字节流)类型的。如果它是字典,可以先用 urllib.parse 模块里的 urlencode() 编码。
  • headers:是一个字典,它就是请求头,可以在构造请求时通过 headers 参数直接构造,也可以通过调用请求实例的 add_header() 方法添加。添加请求头最常用的用法就是通过修改 User-Agent 来伪装浏览器,默认的 User-Agent 是 Python-urllib,我们可以通过修改它来伪装浏览器。
  • origin_req_host:指的是请求方的 host 名称或者 IP 地址。
  • unverifiable:表示这个请求是否是无法验证的,默认是 False,意思就是说用户没有足够权限来选择接收这个请求的结果。例如,我们请求一个 HTML 文档中的图片,但是我们没有自动抓取图像的权限,这时 unverifiable 的值就是 True。
  • method:是一个字符串,用来指示请求使用的方法,比如 GET、POST 和 PUT 等。
import urllib.request
import urllib.parse

url = 'http://www.baidu.com/'

# 定制要伪装的头部
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
}
# 构建请求对象
request = urllib.request.Request(url=url, headers=headers)
# 发送请求
response = urllib.request.urlopen(request)
print(response.read().decode())

urllib.request.urlretrieve()

将获取到的 URL 内容保存到当前文件夹,简单举例:

import urllib.request

url = 'https://cdn.jsdelivr.net/gh/AngelNI/CDN@3.0/imgs/avatar.png'

# response = urllib.request.urlopen(image_url)
# with open('angelni.png', 'wb') as fp:
#    fp.write(response.read())

urllib.request.urlretrieve(url, 'angelni.png')

urllib.error 异常处理

URLError

如果打开一个不存在的页面,就会出现 URLError 错误,该错误有一个 reason 属性,用于返回错误的原因。简单举例:

from urllib import request, error  
try:  
    response = request.urlopen('https://angelni.github.io/index/')  
except error.URLError as e:  
    print(e.reason)

运行结果

Not Found

HTTPError

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

  • code:返回 HTTP 状态码,比如 404 表示网页不存在,500 表示服务器内部错误等。
  • reason:同父类一样,用于返回错误的原因。
  • headers:返回请求头。

简单举例:

from urllib import request, error  
try:  
    response = request.urlopen('https://angelni.github.io/index/')  
except error.HTTPError as e:  
    print(e.code, e.reason, e.headers)

运行结果

404 Not Found Connection: close
Content-Length: 14054
Content-Type: text/html; charset=utf-8
Server: GitHub.com
Strict-Transport-Security: max-age=31556952
ETag: "5eb8e4ca-36e6"
Access-Control-Allow-Origin: *
X-Proxy-Cache: MISS
X-GitHub-Request-Id: 6496:45A5:369AC6:3A1948:5EC76895
Accept-Ranges: bytes
Date: Fri, 22 May 2020 05:59:06 GMT
Via: 1.1 varnish
Age: 403
X-Served-By: cache-tyo19926-TYO
X-Cache: HIT
X-Cache-Hits: 1
X-Timer: S1590127147.595289,VS0,VE0
Vary: Accept-Encoding
X-Fastly-Request-ID: b2a7e9ca856a64157cd67ea4a59e449062baa169

进阶用法

因为 URLError 是 HTTPError 的父类,所以可以先选择捕获子类的错误,再去捕获父类的错误,前面的代码改进:

from urllib import request, error  

try:  
    response = request.urlopen('https://angelni.github.io/index/')  
except error.HTTPError as e:  
    print(e.reason, e.code, e.headers)  
except error.URLError as e:  
    print(e.reason)  
else:  
    print('Request Successfully')

urllib.parse 解析 URL

urllib.parse.urlencode()

将字典参数序列化为 GET 请求参数,示例:

from urllib.parse import urlencode
data = {
    'ie': 'utf-8',
    'wd': 'TRHX',
}
base_url = 'http://www.baidu.com?'
url = base_url + urlencode(data)
print(url)

运行结果

http://www.baidu.com?ie=utf-8&wd=TRHX

urllib.parse.parse_qs()

与 urlencode() 相反,将 GET 请求参数反序列化转回字典,示例:

from urllib.parse import parse_qs
query = 'name=TRHX&age=20'
print(parse_qs(query))

运行结果

{'name': ['TRHX'], 'age': ['20']}

urllib.parse.parse_qsl()

将参数转化为元组组成的列表,示例:

from urllib.parse import parse_qsl
query = 'name=TRHX&age=20'
print(parse_qsl(query))

运行结果

[('name', 'TRHX'), ('age', '20')]

urllib.parse.urlparse()

对 URL 进行分段,返回 6 个结果,示例:

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

运行结果

<class 'urllib.parse.ParseResult'> ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')

返回结果为 ParseResult 类型的对象,含 scheme、netloc、path、params、query 和 fragment 6 个部分,依次代表协议、域名、路径、参数、查询条件、锚点

urllib.parse.urlunparse()

与 urlparse() 相反,对 URL 进行组合,传入的参数是一个可迭代对象,长度必须是 6,否则会抛出参数数量不足或者过多的问题,示例:

from urllib.parse import urlunparse  
data = ['http', 'www.baidu.com', 'index.html', 'user', 'a=6', 'comment']  
print(urlunparse(data))

运行结果

http://www.baidu.com/index.html;user?a=6#comment

urllib.parse.urlsplit()

与 urlparse() 方法相似,但是它不再单独解析 params 部分,只返回 5 个结果。params 会合并到 path 中,示例:

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

运行结果

SplitResult(scheme='http', netloc='www.baidu.com', path='/index.html;user', query='id=5', fragment='comment')

urllib.parse.urlunsplit()

与 urlunparse() 方法类似,对 URL 进行组合,传入的参数也是一个可迭代对象,长度必须为 5,示例:

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

运行结果

http://www.baidu.com/index.html?a=6#comment

urllib.parse.urljoin()

对 URL 进行组合,提供两个 URL 作为两个参数,将会自动分析 URL 的 scheme、netloc 和 path 这 3 个内容并对新链接缺失的部分进行补充,最后返回结果,示例:

from urllib.parse import urljoin  
print(urljoin('http://www.baidu.com', 'friends.html'))  
print(urljoin('http://www.baidu.com', 'https://www.itrhx.com/friends.html'))  
print(urljoin('http://www.baidu.com/friends.html', 'https://www.itrhx.com/friends.html'))  
print(urljoin('http://www.baidu.com/friends.html', 'https://www.itrhx.com/friends.html?id=2'))  
print(urljoin('http://www.baidu.com?wd=trhx', 'https://www.itrhx.com/index.html'))  
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'))

运行结果

http://www.baidu.com/friends.html
https://www.itrhx.com/friends.html
https://www.itrhx.com/friends.html
https://www.itrhx.com/friends.html?id=2
https://www.itrhx.com/index.html
http://www.baidu.com?category=2#comment
www.baidu.com?category=2#comment
www.baidu.com?category=2

urllib.parse.quote()

将内容转化为 URL 编码的格式。当 URL 中带有中文参数时,可以将中文字符转化为 URL 编码,示例:

from urllib.parse import quote
keyword = '中国'  
url = 'https://www.baidu.com/s?wd=' + quote(keyword)  
print(url)

运行结果

https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD

urllib.parse.unquote()

与 quote() 方法相反,对 URL 进行解码,示例:

from urllib.parse import unquote  
url = 'https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD'  
print(unquote(url))

运行结果

https://www.baidu.com/s?wd=中国

urllib.robotparser 爬取权限判断

Robots 协议简介

Robots 协议即爬虫协议,用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取。它通常是一个叫作 robots.txt 的文本文件,一般放在网站的根目录下。

robots.txt 基本格式:

User-agent:
Disallow:
Allow:
  • User-agent 为搜索爬虫的名称,设置为 * 则表示对任何爬虫皆有效;
  • Disallow 指定了不允许抓取的目录,设置为 / 则代表不允许抓取所有页面;
  • Allow 指定了允许抓取的目录,一般和 Disallow 一起使用,一般不会单独使用,用来排除某些限制。

RobotFileParser 类常用方法

RobotFileParser 类的声明:

urllib.robotparser.RobotFileParser(url='')

常用方法及其解释:

  • set_url:用来设置 robots.txt 文件的链接。如果在创建 RobotFileParser 对象时传入了链接,那么就不需要再用这种方法了。
  • read:读取 robots.txt 文件并进行分析。此方法执行一个读取和分析操作,若不调用此方法,接下来的判断都会为 False,这个方法不会返回任何内容,但是执行了读取操作。
  • parse:解析 robots.txt 文件,传入的参数是 robots.txt 某些行的内容,它会按照 robots.txt 的语法规则来分析这些内容。
  • can_fetch:该方法传入两个参数,第一个是 User-agent,第二个是要抓取的 URL。返回的内容是该搜索引擎是否可以抓取这个 URL,返回结果是 True 或 False。
  • mtime:返回的是上次抓取和分析 robots.txt 的时间,此方法可以定期检查来抓取最新的 robots.txt。
  • modified:将当前时间设置为上次抓取和分析 robots.txt 的时间。

以简书为例

from urllib.robotparser import RobotFileParser
rp = RobotFileParser()
rp.set_url('http://www.jianshu.com/robots.txt')
rp.read()
print(rp.can_fetch('*', 'https://www.jianshu.com/p/6d9527300b4c'))
print(rp.can_fetch('*', "http://www.jianshu.com/search?q=python&page=1&type=collections"))
False
False
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-05-22|,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基本库 urllib 的使用
    • urllib 简介
      • urllib.request
        • urllib.request.urlopen()
        • urllib.request.Request()
        • urllib.request.urlretrieve()
      • urllib.error 异常处理
        • URLError
        • HTTPError
        • 进阶用法
      • urllib.parse 解析 URL
        • urllib.parse.urlencode()
        • urllib.parse.parse_qs()
        • urllib.parse.parse_qsl()
        • urllib.parse.urlparse()
        • urllib.parse.urlunparse()
        • urllib.parse.urlsplit()
        • urllib.parse.urlunsplit()
        • urllib.parse.urljoin()
        • urllib.parse.quote()
        • urllib.parse.unquote()
      • urllib.robotparser 爬取权限判断
        • Robots 协议简介
        • RobotFileParser 类常用方法
    相关产品与服务
    内容分发网络 CDN
    内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档