前言
爬虫也了解了一段时间了希望在半个月的时间内结束它的学习, 开启 python 的新大陆, 今天大致总结一下爬虫基础相关的类库 ---Urllib
Urllib
官方文档地址: https://docs.python.org/3/library/urllib.html
urllib 提供了一系列用于操作 URL 的功能
Python3 中将 python2.7 的 urllib 和 urllib2 两个包合并成了一个 urllib 库, 其主要包括一下模块:
urllib.request 请求模块
urllib.error 异常处理模块
urllib.parse url 解析模块
urllib.robotparser robots.txt 解析模块
- urllib.request
- urllib.request.urlopen
通过案例可以看出 urlopen, 会返回一个二进制的对象, 对这个对象进行 read() 操作可以得到一个包含网页的二进制字符串, 然后用 decode() 解码成一段 html 代码
urlopen 参数如下:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
常用参数:
url: 访问的地址, 一般不只是地址
data: 此参数为可选字段, 特别要注意的是, 如果选择, 请求变为 post 传递方式, 其中传递的参数需要转为 bytes, 如果是我们只需要通过 urllib.parse.urlencode 转换即可:
- import urllib.parse
- import urllib.request
- data = bytes(urllib.parse.urlencode({'word': 'hello'}), encoding= 'utf8')
- response = urllib.request.urlopen('http://xxxxx', data=data)
- print(response.read().decode('utf-8'))
timeout: 设置网站的访问超时时间
其他参数:
context 参数: 它必须是 ssl.SSLContext 类型, 用来指定 SSL 设置
cafile 和 capath 两个参数: 是指定 CA 证书和它的路径, 这个在请求 HTTPS 链接时会有用
cadefault 参数: 现在已经弃用了, 默认为 False
urlopen 返回对象提供方法:
read() , readline() ,readlines() , fileno() , close() : 对 HTTPResponse 类型数据进行操作
info(): 返回 HTTPMessage 对象, 表示远程服务器返回的头信息
getcode(): 返回 Http 状态码
geturl(): 返回请求的 url
- import urllib.request
- response = urllib.request.urlopen('http://python.org/')
- print("查看 response 的返回类型:",type(response))
- print("查看反应地址信息:",response)
- print("查看头部信息 1(http header):\n",response.info())
- print("查看头部信息 2(http header):\n",response.getheaders())
- print("输出头部属性信息:",response.getheader("Server"))
- print("查看响应状态信息 1(http status):\n",response.status)
- print("查看响应状态信息 2(http status):\n",response.getcode())
- print("查看响应 url 地址:\n",response.geturl())
- page = response.read()
- print("输出网页源码:",page.decode('utf-8'))
- View Code
- urllib.request.Request
- import urllib.request
- headers = {'Host': 'www.xicidaili.com',
- 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
- 'Accept': r'application/json, text/javascript, */*; q=0.01',
- 'Referer': r'http://www.xicidaili.com/', }
- req = urllib.request.Request(r'http://www.xicidaili.com/nn/', headers=headers)
- response = urllib.request.urlopen(req)
- html = response.read().decode('utf-8')
- print(html)
通过代码我们可以看出 urlopen 不再是传递 url 了, 而是一个 request 这样一来我们不带把请求独立成一个对象, 而且能更加灵活方便的配置访问参数, 这是爬虫 http 必不可少的一步
Request 参数如下:
urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
常用参数:
url: 访问的地址
data: 此参数为可选字段, 其中传递的参数需要转为 bytes, 如果是字典我们只需要通过 urllib.parse.urlencode 转换即可:
headers:http 相应 headers 传递的信息, 构造方法: headers 参数传递, 通过调用 Request 对象的 add_header() 方法来添加请求头 python 3.x 爬虫基础 ---http headers 详解, 可参考此文章
其他参数:
origin_req_host : 指的是请求方的 host 名称或者 IP 地址
unverifiable : 用来表明这个请求是否是无法验证的, 默认是 False 意思就是说用户没有足够权限来选择接收这个请求的结果如果没有权限, 这时 unverifiable 的值就是 True
method : 用来指示请求使用的方法, 比如 GET , POST , PUT 等
urllib.request.ProxyHandler(ip 代理)
以上做些简单的 demo 是没有问题的, 但是如果想让你的爬虫更加强大, 那么 rulllib.request.ProxyHandler 设置代理你一定要知道, 网站它会检测某一段时间某个 IP 的访问次数, 如果访问次数过多, 它会禁止你的访问, 所以这个时候需要通过设置代理来爬取数据
- ef Proxy_read(proxy_list, user_agent_list, i):
- proxy_ip = proxy_list[i]
- print('当前代理 ip:%s'%proxy_ip)
- user_agent = random.choice(user_agent_list)
- print('当前代理 user_agent:%s'%user_agent)
- sleep_time = random.randint(1,3)
- print('等待时间:%s s' %sleep_time)
- time.sleep(sleep_time)
- print('开始获取')
- headers = {'User-Agent': user_agent,'Accept': r'application/json, text/javascript, */*; q=0.01',
- 'Referer': r'https://www.cnblogs.com'
- }
- proxy_support = request.ProxyHandler({'http':proxy_ip})
- opener = request.build_opener(proxy_support)
- request.install_opener(opener)
- req = request.Request(r'https://www.cnblogs.com/kmonkeywyl/p/8409715.html',headers=headers)
- try:
- html = request.urlopen(req).read().decode('utf-8')
- except Exception as e:
- print('****** 打开失败!******')
- else:
- global count
- count +=1
- print('OK! 总计成功 %s 次!'%count)
以上代码是前段时间写的刷新页面的但是没有达到想要的效果, 不过里面有用到 request.ProxyHandler({'http':proxy_ip}) 其中 urllib.request.build_opener() 方法来利用这个处理器构建一个 Opener , 那么这个 Opener 在发送请求的时候就具备了认证功能了 request.install_opener(opener) 方法打开链接, 就可以完成认证了
urllib.request.HTTPCookieProcessor(cookie 操作)
网站中通过 cookie 进行判断权限是很常见的那么我们可以通过 urllib.request.HTTPCookieProcessor(cookie) 来操作 cookie 使用 Cookie 和使用代理 IP 一样, 也需要创建一个自己的 opener 在 HTTP 包中, 提供了 cookiejar 模块, 用于提供对 Cookie 的支持 http.cookiejar 功能强大, 我们可以利用本模块的 CookieJar 类的对象来捕获 cookie 并在后续连接请求时重新发送, 比如可以实现模拟登录功能该模块主要的对象有 CookieJarFileCookieJarMozillaCookieJarLWPCookieJar
获取 cookie( CookieJar)
- import http.cookiejar, urllib.request
- cookie = http.cookiejar.CookieJar()
- handler = urllib.request.HTTPCookieProcessor(cookie)
- opener = urllib.request.build_opener(handler)
- response = opener.open('http://www.baidu.com')
- for item in cookie:
- print(item.name+"="+item.value)
- View Code
保存 cookie(MozillaCookieJar)
- filename = 'cookie.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)
- View Code
使用 cookie
- import http.cookiejar, urllib.request
- cookie = http.cookiejar.MozillaCookieJar()
- cookie.load('cookie.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'))
- View Code
其中 FileCookieJarMozillaCookieJarLWPCookieJar 约为保存 cookie 信息, 只是保存格式不同我们在进行操作 cookie 时使用对应的格式即可
urllib.error
用 try-except 来捕捉异常, 主要的错误方式就两种 URLError(错误信息) 和 HTTPError(错误编码).
- try:
- data=urllib.request.urlopen(url)
- print(data.read().decode('utf-8'))
- except urllib.error.HTTPError as e:
- print(e.code)
- except urllib.error.URLError as e:
- print(e.reason)
- urllib.parse
- urllib.parse.urlparse
将对应的 URL 解析成六部分, 并以元组的数据格式返回来
- import urllib.parse
- o = urllib.parse.urlparse('http://www.cnblogs.com/kmonkeywyl/')
- print(o)
参数
result = urlparse('url',scheme='https') 解析协议 可以去掉 http://
result = urlparse('url',scheme='http')
result = urlparse('url',allow_fragments=False) url 带有查询参数
result = urlparse('url',allow_fragments=False) url 不带有查询参数
urllib.parse.urlunparse
拼接 url
- from urllib.parse
- data = ['http','www.baidu.com','index.html','user','a=1','comment']
- print(urllib.parse.urlunparse(data))
urllib.parse.urljoin
用来拼接 url 的方法 或者叫组合方法, url 必须为一致站点, 否则后面参数会覆盖前面的 host
- from urllib.parse import urljoin
- print(urljoin('http://www.baidu.com','FAQ.html'))
- print(urljoin('http://www.badiu.com','https://www.baidu.com/FAQ.html'))
- print(urljoin('http://www.baidu.com/about.html','http://www.baidu.com/FAQ.html'))
- print(urljoin('www.baidu.com#comment','?category=2'))
这个在这个就不过多的介绍了, 有兴趣的可以去看资料
来源: https://www.cnblogs.com/kmonkeywyl/p/8458442.html