urlib库为python3的HTTP内置请求库
urilib的四个模块:
-
urllib.request:用于获取网页的响应内容
-
urllib.error:异常处理模块,用于处理异常的模块
-
urllib.parse:用于解析url
-
urllib.robotparse:用于解析robots.txt,主要用于看哪些网站不能进行爬取,不过少用
1. urllib.request
urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None,cadefault=False,context=None)
-
url:为请求网址
-
data:请求时需要发送的参数
-
timeout:超时设置,在该时间范围内返回请求内容就不会报错
from urllib import request # 请求获取网页返回内容 response = request.urlopen('https://movie.douban.com/') # 获取网页返回内容 print(response.read().decode('utf-8')) # 获取状态码 print(response.status) # 获取请求头 print(response.getheaders())
# 对请求头进行遍历 for k, v in response.getheaders(): print(k, '=', v)
可以使用上面的代码对一些网站进行请求了,但是当需要一些反爬网站时,这就不行了,这时我们需要适当地增加请求头进行请求,这时就需要使用复杂一点的代码了,这时我们需要用到Request对象
# 请求头 headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0'} requests = request.Request('https://movie.douban.com/', headers=headers) # 加入自己的请求头更加接近浏览器 # 进行请求,把Request对象传入urlopen参数中 response = request.urlopen(requests) print(response.read().decode('utf-8'))
这个我添加了请求头进行请求,使我发送的请求更加接近浏览器的行为。可以对应一些反爬网站了。如果网站需要进行登陆,这时需要用到post方法,用上面的也是可以的。
from urllib import request, parse # 使用post方法来进行模拟登陆豆瓣 data = {'source': 'None', 'redir': 'https://www.douban.com/', 'form_email': '*****@qq.com', 'form_password': '***', 'remember': 'on', 'login': '登录'} # 将data的字典类型转换为get请求方式 data=bytes(parse.urlencode(data),encoding='utf-8') requests = request.Request('https://accounts.douban.com/login', headers=headers, data=data, method='POST') response = request.urlopen(requests) print(response.read().decode('utf-8'))
这里我用到了data的参数把登陆需要的参数传进去,还加了个请求方法Method
parse.urlencode()后面有讲
这里还有另外一种添加请求头的方法
Request.add_header(): 参数有两个,分别为请求头对应的键和值,这种方法一次只能添加一个请求头,添加多个需要用到循环或者直接用前面的方法添加多个请求头
在登陆了网站之后,我们需要用到cookie来保存登陆信息,这时就需要获取cookie了。urllib获取cookie比较麻烦
from http import cookiejar # 获取cookie cookie = cookiejar.CookieJar() # 获取助手把cookie传进去 handler = request.HTTPCookieProcessor(cookie) # 获取opener进行请求网站 opener = request.build_opener(handler) # 请求网页 response = opener.open('https://movie.douban.com/') # 打印cookie for c in cookie: print(c.name, '=', c.value)
单纯地打印没什么用,我们需要把他存入文件来保存,下次使用时再次加载cookie来登陆
保存cookie为文件:
from http import cookiejar #将cookie保存在文件中 filename='cookie.txt' cookie=cookiejar.MozillaCookieJar(filename)#表示使用Mozilla的cookie方式存储和读取 handler=request.HTTPCookieProcessor(cookie) opener=request.build_opener(handler) opener.open('https://movie.douban.com/') #保存文件 cookie.save(ignore_discard=True,ignore_expires=True)
另一种保存方法:
from http import cookiejar cookie=cookiejar.LWPCookieJar(filename)#表示Set-Cookie3文件格式存储和读取 handler=request.HTTPCookieProcessor(cookie) opener=request.build_opener(handler) opener.open('https://movie.douban.com/') #保存文件 cookie.save(ignore_discard=True,ignore_expires=True)
这两种保存格式都是不一样的,需要保存的内容一样。
保存可以了,这时就需要用到加载了,当然也可以。代码如下:
from http import cookiejar # 从cookie文件加载到网页上实现记住登陆 cookie = cookiejar.LWPCookieJar() # 加载文件 cookie.load(filename, ignore_discard=True, ignore_expires=True) handler = request.HTTPCookieProcessor(cookie) opener = request.build_opener(handler) opener.open('https://movie.douban.com/')
这样就可以实现不用密码进行登陆了。
cookie小总结:在操作cookie时,都是分五步,如下:
-
进行导包,至关重要的一步,不导包直接出错。
-
获取cookie处理对象,使用cookiejar包
-
创建cookie处理器,使用request.HTTPCookieJarProcessor()
-
利用cookie处理器构建opener,使用request.build_opener()
-
进行请求网站,用opener.open(),这个不能用request.urlopen()
如果有时你在同一ip连续多次发送请求,会有被封ip的可能,这时我们还需要用到代理ip进行爬取,代码如下:
proxy = request.ProxyHandler({'https': 'https://106.60.34.111:80'}) opener = request.build_opener(proxy) opener.open('https://movie.douban.com/',timeout=1)
2. urllib.error
将上面的使用代理ip的请求进行异常处理,如下:
from urllib import request, error try: proxy = request.ProxyHandler({ 'https': 'https://106.60.34.111:80' }) opener = request.build_opener(proxy) opener.open('https://movie.douban.com/', timeout=1) except error.HTTPError as e: print(e.reason(), e.code(), e.headers()) except error.URLError as e: print(e.reason)
因为有时这个ip或许也被封了,有可能会抛出异常,所以我们为了让程序运行下去进而进行捕捉程序
-
error.URLError: 这个是url的一些问题,这个异常只有一个reason属性
-
error.HTTPError:这个是error.URLError的子类,所以在与上面的混合使用时需要将这个异常放到前面,这个异常是一些请求错误,有三个方法,.reason(), .code(), .headers(),所以在捕捉异常时通常先使用这个
3. urllib.parse
解析url:urllib.parse.urlparse(url, scheme='', allow_fragments=True)
简单的使用:
from urllib import request, parse # 解析url print(parse.urlparse('https://movie.douban.com/')) print(parse.urlparse('https://movie.douban.com/', scheme='http')) print(parse.urlparse('movie.douban.com/', scheme='http')) #结果 #ParseResult(scheme='https', netloc='movie.douban.com', path='/', params='', query='', fragment='') #ParseResult(scheme='https', netloc='movie.douban.com', path='/', params='', query='', fragment='') #ParseResult(scheme='http', netloc='', path='movie.douban.com/', params='', query='', fragment='')
可以看出加了scheme参数和没加的返回结果是有区别的。而当scheme协议加了,而前面的url也包含协议,一般会忽略后面的scheme参数
既然有解析url,那当然也有反解析url,就是把元素串连成一个url
from urllib import parse # 将列表元素拼接成url url = ['http', 'www', 'baidu', 'com', 'dfdf', 'eddffa'] # 这里至少需要6个元素(我乱写的,请忽视) print(parse.urlunparse(url)) # 下面是结果 # http://www/baidu;com?dfdf#eddffa
urlparse()接收一个列表的参数,而且列表的长度是有要求的,是必须六个参数以上,要不会抛出异常
1Traceback (most recent call last): 2 File "E:/anaconda/python_project/python3_spider/urllib_test.py", line 107, in <module> 3 print(parse.urlunparse(url)) 4 File "E:anacondaliburllibparse.py", line 454, in urlunparse 5 _coerce_args(*components)) 6ValueError: not enough values to unpack (expected 7, got 6)
urllib.parse.urljoin():这个是将第二个参数的url缺少的部分用第一个参数的url补齐
# 连接两个参数的url, 将第二个参数中缺的部分用第一个参数的补齐 print(parse.urljoin('https://movie.douban.com/', 'index')) print(parse.urljoin('https://movie.douban.com/','https://accounts.douban.com/login')) # 下面是结果 #https://movie.douban.com/index #https://accounts.douban.com/login
urllib.parse.urlencode():这个方法是将字典类型的参数转为请求为get方式的字符串
data = {'name': 'sergiojuue', 'sex': 'boy'} data = parse.urlencode(data) print('https://accounts.douban.com/login'+data) # 下面是结果 #https://accounts.douban.com/loginname=sergiojuue&sex=boy
4. 结语
还有个urllib.robotparse库少用,就不说了,留给以后需要再去查文档吧。
上面的只是我在学习过程中的总结,如果有什么错误的话,欢迎在留言区指出,还有就是需要查看更多用法的请查看文档https://docs.python.org/3/library/urllib.html
学习过程中看的大多是崔庆才大佬的视频:https://edu.hellobi.com/course/157
感谢!:https://mp.weixin.qq.com/s?__biz=MzI5NDY1MjQzNA==&mid=2247485940&idx=1&sn=3fabf8c9bb52395675cd71db65cc9109&chksm=ec5ed689db295f9f01f9eb56b95a25fe8221e516969a7ec30794e41fd51fbe582add5002decd&mpshare=1&scene=1&srcid=0329HJXcKhalaWwriIvQ95r7&pass_ticket=jt1ntJmxsOysHtvsCD6R975Ofkvtsc8maZ4Fep%2FuRAov9uL%2Fo%2BMRdbYALU2UxCY0#rd