Python--urllib
urllib
request
最基本的http请求模块
build_opener 函数
使用一些默认的handler构建一个opener(OpenerDirector类型)
urlopen 函数
最基本的构造HTTP请求的方法,实际这个函数内部就是使用build_opener完成创建opener,然后由opener完成请求
- 参数
- data: 二进制,如果传入了此参数,请求方式是POST
- timeout: 超时时间
- context: ssl.SSLContext类型
- cafile: CA证书
- capath: CA证书路径
- 返回值
- http.client.HTTPResponse类型,包含以下方法和属性
- 方法: read, readinfo, getheader, getheaders, fileno
- 属性: msg, version, status, reason, debuglevel, closed
- 返回状态: status
- 返回的数据: read(),如果是文本,可以:read().decode('utf-8)
- http.client.HTTPResponse类型,包含以下方法和属性
OpenerDirector 类
实际上请求都是由这个类的实例完成
open 方法
发起请求
Request 类
可以构建更复杂的HTTP请求,比如添加headers
init 方法
- 参数
- headers: 字典形式的headers
add_header 方法
添加请求头,如果已经存在会覆盖原来的值,否则新增
BaseHandler 类
各种handler的父类
HTTPDefaultErrorHandler 类
用于处理HTTP响应错误,所有错误都会抛出HTTPError类型的异常
HTTPRedirectHandler 类
用于处理重定向
HTTPCookieProcessor 类
用于处理Cookie
ProxyHandler 类
用于设置代理,代理默认为空
HTTPPasswordMgr 类
用于管理密码,它维护着用户名密码的对照表
HTTPBasicAuthHandler 类
用于管理认证,如果一个链接在打开时需要认证,那么可以用这个类来解决认证问题
parse
工具模块,用来对URL进行解析,合并等操作
urlparse 函数
实现URL的识别和分段,结果包含6部分:scheme://netloc/path;params?query#fragment
-
参数
- urlstring: 即待解析的url
- scheme: 如果url中不包含scheme,则此参数作为默认值
- allow_fragments: True(默认)/False,如果设置为False,则解析后的fragment为空字符串,对应的数据会被解析为path、params或者query的一部分,一般前面三者谁在最后就跟谁
-
返回值
- urllib.parse.ParseResult
- 可以直接.属性获取相关部分的数据,也可以使用[下标]的方式
urlunparse 函数
这个函数用于构造url,即urlparse的逆操作
- 参数
- components:包含6个元素的可迭代对象,多了或者少了都会报错
urlsplit 函数
与方法urlparse类似,只是会把params部分合并到path中,结果只有5部分
- 返回值
- urllib.parse.SplitResult
urlunsplit 函数
urlsplit的逆操作
urljoin 函数
常用于拼接 base_url和path
把base链接里面的部分填充到新url中对应缺失的部分
- 参数
- base: 基础链接
- url: 新url
- allow_fragments
urlencode 函数
可以将字典类型转成GET请求参数
parse_qs 函数
urlencode的逆操作,结果是字典类型
parse_qsl 函数
同parse_qs,结果是列表类型
quote 函数
对内容进行url编码
unquote 函数
quote的逆操作
error
异常处理模块
URLError 类
其他异常类的基类
- 属性
- reason
HTTPError 类
专门处理HTTP请求错误
- 属性
- code
- reason
- headers
robotparser
处理网站robot.txt文件
RobotFileParser 类
用来解析robots.txt文件,并可以判断是否能爬取指定的url
parse 方法
- 参数
- lines: robots.txt文件中的一行行
can_fetch 方法
判断某个useragent是否能爬取某个url
- 参数
- useragent:
- url:
import datetime
import http.cookiejar
import time
from urllib import request, parse, error, robotparser
def test_urlopen():
url_get = 'https://www.httpbin.org/get'
url_post = 'https://www.httpbin.org/post'
data = bytes(parse.urlencode({'name': 'post'}), encoding='utf-8')
print(datetime.datetime.now())
try:
response = request.urlopen(url_get)
# response = request.urlopen(url_post, data=data)
print(response.status)
print(response.read().decode('utf-8'))
except Exception as e:
print(f'异常: {e}')
print(datetime.datetime.now())
def test_Request():
print('Request'.center(50, '='))
url_post = 'https://www.httpbin.org/post'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36',
}
req = request.Request(url_post, headers=headers, data=data)
req.add_header('User-Agent', 'mycrawler')
req.add_header('My', 'Yep')
response = request.urlopen(req)
print(response.status)
print(response.read().decode('utf-8'))
def test_auth_handler():
print('HTTPBasicAuthHandler'.center(50, '='))
username = 'admin'
password = 'admin'
url = 'https://ssr3.scrape.center'
p = request.HTTPPasswordMgrWithDefaultRealm()
p.add_password(None, url, username, password)
auth_handler = request.HTTPBasicAuthHandler(p)
opener = request.build_opener(auth_handler)
try:
response = opener.open(url)
print(response.status, response.read().decode('utf-8'))
except error.URLError as e:
print(e.reason)
def test_proxy_handler():
print('ProxyHandler'.center(50, '='))
proxy_handler = request.ProxyHandler({
'http': 'http://127.0.0.1:8080',
'https': 'https://127.0.0.1:8080',
})
opener = request.build_opener(proxy_handler)
try:
response = opener.open('https://www.baidu.com')
print(response.status, response.read().decode('utf-8'))
except error.URLError as e:
print(e.reason)
def test_cookie_processor():
print('HTTPCookieProcessor'.center(50, '='))
cookie = http.cookiejar.CookieJar()
handler = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(handler)
response = opener.open('https://www.baidu.com')
for item in cookie:
print(item.name + '=' + item.value)
def test_cookie_file():
print('cookie_file'.center(50, '='))
cookie_file = 'cookie.txt'
# cookie = http.cookiejar.MozillaCookieJar(cookie_file)
cookie = http.cookiejar.LWPCookieJar(cookie_file)
handler = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(handler)
response = opener.open('https://www.baidu.com')
cookie.save(ignore_expires=True, ignore_discard=True)
def test_read_cookie_file():
print('read cookie_file'.center(50, '='))
# cookie = http.cookiejar.LWPCookieJar()
# cookie.load(cookie_file, ignore_discard=True, ignore_expires=True)
# for item in cookie:
# print(item.name + '=' + item.value) # 这里有输出,说明读取成功了
# handler = request.HTTPCookieProcessor(cookie)
# opener = request.build_opener(handler)
# # 貌似不起作用,返回的cookie没有数据
# response = opener.open('https://www.httpbin.org/cookies')
# 下面这种方式可以返回cookie数据
req = request.Request('https://www.httpbin.org/cookies', headers={'Cookie':'BIDUPSID=2189E52DAAF0E09623AD53F9D29B9F81'})
response = opener.open(req)
print(response.read().decode('utf-8'))
def test_urlparse():
print('urlparse'.center(50, '='))
# url不带scheme,netloc部分被解析到了path
# url = 'www.baidu.com/index.html;user?id=5#comment'
url = 'http://www.baidu.com/index.html;user?id=5#comment'
result = parse.urlparse(url, scheme='https')
# result = parse.urlparse(url, allow_fragments=False)
print(type(result))
print(result)
print(type(result.fragment))
'''
<class 'urllib.parse.ParseResult'>
ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')
<class 'str'>
'''
def test_urlunparse():
print('urlunparse'.center(50, '='))
url = parse.urlunparse(['https', 'www.baidu.com', '/index.html', 'user', 'id=5', 'comment'])
print(url)
def test_urljoin():
print('urljoin'.center(50, '='))
print(parse.urljoin('https://www.baidu.com', 'index.html'))
print(parse.urljoin('https://www.baidu.com', 'www.cnblogs.com/index.html'))
print(parse.urljoin('https://www.baidu.com', 'http://www.cnblogs.com/index.html'))
'''
https://www.baidu.com/index.html
https://www.baidu.com/www.cnblogs.com/index.html
http://www.cnblogs.com/index.html
'''
def test_urlencode():
print('urlencode'.center(50, '='))
data = {
'name': ['名称', '名称2'],
'password': '密码'
}
# 当一个key有多个值时,字典的方式得到的结果不对,会把整个list作为整体进行encode
# data = {'name': ['名称', '名称2'], 'password': ['密码']}
# 需要使用列表的方式
# data = [('name', '名称'), ('name', '名称2'), ('password', '密码')]
base_url = 'https://www.baidu.com?'
print(base_url + parse.urlencode(data))
'''
https://www.baidu.com?name=%E5%90%8D%E7%A7%B0&password=%E5%AF%86%E7%A0%81
'''
def test_parse_qs():
print('parse_qs'.center(50, '='))
# url = 'https://www.baidu.com?name=%E5%90%8D%E7%A7%B0&password=%E5%AF%86%E7%A0%81'
# url = 'https://www.baidu.com?name=名称&name=名称2&password=密码'
# 这种方式解析出来的name值是字符串,而不是数组
url = 'https://www.baidu.com?name=%5B%27%E5%90%8D%E7%A7%B0%27%2C+%27%E5%90%8D%E7%A7%B02%27%5D&password=%5B%27%E5%AF%86%E7%A0%81%27%5D'
'''
qs: {'name': ["['名称', '名称2']"], 'password': ["['密码']"]}
qsl: [('name', "['名称', '名称2']"), ('password', "['密码']")]
'''
query = parse.urlparse(url).query
print(query)
# data = parse.parse_qs(query)
data = parse.parse_qsl(query)
print(data)
''' parse_qs
name=%E5%90%8D%E7%A7%B0&password=%E5%AF%86%E7%A0%81
{'name': ['名称'], 'password': ['密码']}
'''
''' parse_qsl
name=%E5%90%8D%E7%A7%B0&password=%E5%AF%86%E7%A0%81
[('name', '名称'), ('password', '密码')]
'''
def test_quote():
print('quote'.center(50, '='))
print(parse.quote('名称'))
print(parse.quote('https://www.baidu.com?name=名称&name=名称2&password=密码'))
print(parse.quote('https://www.baidu.com?name=名称&name=名称2&password=密码', safe=''))
'''
%E5%90%8D%E7%A7%B0
https%3A//www.baidu.com%3Fname%3D%E5%90%8D%E7%A7%B0%26name%3D%E5%90%8D%E7%A7%B02%26password%3D%E5%AF%86%E7%A0%81
https%3A%2F%2Fwww.baidu.com%3Fname%3D%E5%90%8D%E7%A7%B0%26name%3D%E5%90%8D%E7%A7%B02%26password%3D%E5%AF%86%E7%A0%81
'''
def test_unquote():
print('unquote'.center(50, '='))
url = 'https%3A%2F%2Fwww.baidu.com%3Fname%3D%E5%90%8D%E7%A7%B0%26name%3D%E5%90%8D%E7%A7%B02%26password%3D%E5%AF%86%E7%A0%81'
print(parse.unquote(url))
'''
https://www.baidu.com?name=名称&name=名称2&password=密码
'''
def test_robots_text():
print('RobotFileParser'.center(50, '='))
rp = robotparser.RobotFileParser()
response = request.urlopen('https://www.baidu.com/robots.txt')
rp.parse(response.read().decode('utf-8').split('\n'))
print(rp.can_fetch('BaiduSpider', 'https://www.baidu.com'))
print(rp.can_fetch('BaiduSpider', 'https://www.baidu.com/homepage/'))
print(rp.can_fetch('Googlebot', 'https://www.baidu.com/homepage/'))
def main():
# test_urlparse()
# test_urlunparse()
# test_urljoin()
# test_urlencode()
# test_parse_qs()
# test_quote()
# test_unquote()
test_robots_text()
if __name__ == '__main__':
main()