Python爬虫常用库之urllib详解

作者: 天善智能 | 来源:发表于2018-04-09 15:15 被阅读17次

    感谢关注天善智能,走好数据之路↑↑↑

    欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定!

    对商业智能BI、大数据分析挖掘、机器学习,python,R等数据领域感兴趣的同学加微信:tstoutiao,邀请你进入数据爱好者交流群,数据爱好者们都在这儿。

    作者:sergiojune 个人公众号:日常学python,原文发表于Python爱好者社区https://mp.weixin.qq.com/s/kbsaw1cwYnS5jdRLva0Izg

    以下为个人在学习过程中做的笔记总结之爬虫常用库urllib

    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:超时设置,在该时间范围内返回请求内容就不会报错

    示例代码:

    1from urllib import request

    2

    3# 请求获取网页返回内容

    4response = request.urlopen('https://movie.douban.com/')

    5# 获取网页返回内容

    6print(response.read().decode('utf-8'))

    7# 获取状态码

    8print(response.status)

    9# 获取请求头

    10print(response.getheaders())

    1# 对请求头进行遍历

    2for k, v in response.getheaders():

    3 print(k, '=', v)

    可以使用上面的代码对一些网站进行请求了,但是当需要一些反爬网站时,这就不行了,这时我们需要适当地增加请求头进行请求,这时就需要使用复杂一点的代码了,这时我们需要用到Request对象

    代码示例:

    1# 请求头

    2headers = {'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'}

    3requests = request.Request('https://movie.douban.com/', headers=headers) # 加入自己的请求头更加接近浏览器

    4# 进行请求,把Request对象传入urlopen参数中

    5response = request.urlopen(requests)

    6print(response.read().decode('utf-8'))

    这个我添加了请求头进行请求,使我发送的请求更加接近浏览器的行为。可以对应一些反爬网站了

    如果网站需要进行登陆,这时需要用到post方法,用上面的也是可以的。代码如下:

    1from urllib import request, parse

    2# 使用post方法来进行模拟登陆豆瓣

    3data = {'source': 'None',

    4'redir': 'https://www.douban.com/',

    5'form_email': 'user',

    6'form_password': 'passwd',

    7'remember': 'on',

    8'login': '登录'}

    9# 将data的字典类型转换为get请求方式

    10data = bytes(parse.urlencode(data), encoding='utf-8')

    11requests = request.Request('https://accounts.douban.com/login', headers=headers, data=data, method='POST')

    12response = request.urlopen(requests)

    13print(response.read().decode('utf-8'))

    这里我用到了data的参数把登陆需要的参数传进去,还加了个请求方法Method

    parse.urlencode()后面有讲

    这里还有另外一种添加请求头的方法

    Request.add_header(): 参数有两个,分别为请求头对应的键和值,这种方法一次只能添加一个请求头,添加多个需要用到循环或者直接用前面的方法添加多个请求头

    在登陆了网站之后,我们需要用到cookie来保存登陆信息,这时就需要获取cookie了。urllib获取cookie比较麻烦。

    代码示例如下:

    1from http import cookiejar

    2# 获取cookie

    3cookie = cookiejar.CookieJar()

    4# 获取助手把cookie传进去

    5handler = request.HTTPCookieProcessor(cookie)

    6# 获取opener进行请求网站

    7opener = request.build_opener(handler)

    8# 请求网页

    9response = opener.open('https://movie.douban.com/')

    10# 打印cookie

    11for c in cookie:

    12 print(c.name, '=', c.value)

    单纯地打印没什么用,我们需要把他存入文件来保存,下次使用时再次加载cookie来登陆

    保存cookie为文件:

    1from http import cookiejar

    2# 将cookie保存在文件中

    3filename = 'cookie.txt'

    4cookie = cookiejar.MozillaCookieJar(filename) # 表示使用Mozilla的cookie方式存储和读取5handler = request.HTTPCookieProcessor(cookie)

    6opener = request.build_opener(handler)

    7opener.open('https://movie.douban.com/')

    8# 保存文件

    9cookie.save(ignore_discard=True, ignore_expires=True)

    另一种保存方法:

    1from http import cookiejar

    2cookie = cookiejar.LWPCookieJar(filename) # 表示 Set-Cookie

    3 文件格式存储和读取3handler = request.HTTPCookieProcessor(cookie)

    4opener = request.build_opener(handler)

    5opener.open('https://movie.douban.com/')

    6# 保存文件

    7cookie.save(ignore_discard=True, ignore_expires=True)

    这两种保存格式都是不一样的,需要保存的内容一样。

    保存可以了,这时就需要用到加载了,当然也可以。代码如下:

    1from http import cookiejar

    2# 从cookie文件加载到网页上实现记住登陆

    3cookie = cookiejar.LWPCookieJar()

    4# 加载文件

    5cookie.load(filename, ignore_discard=True, ignore_expires=True)

    6handler = request.HTTPCookieProcessor(cookie)

    7opener = request.build_opener(handler)

    8opener.open('https://movie.douban.com/')

    这样就可以实现不用密码进行登陆了。

    cookie小总结:在操作cookie时,都是分五步,如下:

    进行导包,至关重要的一步,不导包直接出错。

    获取cookie处理对象,使用cookiejar包

    创建cookie处理器,使用request.HTTPCookieJarProcessor()

    利用cookie处理器构建opener,使用request.build_opener()

    进行请求网站,用opener.open(),这个不能用request.urlopen()

    如果有时你在同一ip连续多次发送请求,会有被封ip的可能,这时我们还需要用到代理ip进行爬取,代码如下:

    1proxy = request.ProxyHandler({

    2'https': 'https://106.60.34.111:80'

    3})

    4opener = request.build_opener(proxy)

    5opener.open('https://movie.douban.com/', timeout=1)

    可以看到越复杂的请求都需要用到request.build_opener(),这个方法有点重要,请记住哈

    2urllib.error

    将上面的使用代理ip的请求进行异常处理,如下:

    1from urllib import request, error

    2try:

    3 proxy = request.ProxyHandler({

    4'https': 'https://106.60.34.111:80'

    5 })

    6 opener = request.build_opener(proxy)

    7 opener.open('https://movie.douban.com/', timeout=1)

    8except error.HTTPError as e:

    9 print(e.reason(), e.code(), e.headers())

    10except error.URLError as e:

    11 print(e.reason)

    因为有时这个ip或许也被封了,有可能会抛出异常,所以我们为了让程序运行下去进而进行捕捉程序

    error.URLError: 这个是url的一些问题,这个异常只有一个reason属性

    error.HTTPError:这个是error.URLError的子类,所以在与上面的混合使用时需要将这个异常放到前面,这个异常是一些请求错误,有三个方法,.reason(), .code(), .headers(),所以在捕捉异常时通常先使用这个

    3urllib.parse

    解析url:urllib.parse.urlparse(url, scheme='', allow_fragments=True)

    简单的使用:

    1from urllib import request, parse

    2# 解析url

    3print(parse.urlparse('https://movie.douban.com/'))

    4print(parse.urlparse('https://movie.douban.com/', scheme='http'))

    5print(parse.urlparse('movie.douban.com/', scheme='http'))

    6# 下面是结果

    7ParseResult(scheme='https', netloc='movie.douban.com', path='/', params='', query='', fragment='')

    8ParseResult(scheme='https', netloc='movie.douban.com', path='/', params='', query='', fragment='')

    9ParseResult(scheme='http', netloc='', path='movie.douban.com/', params='', query='', fragment='')

    可以看出加了scheme参数和没加的返回结果是有区别的。而当scheme协议加了,而前面的url也包含协议,一般会忽略后面的scheme参数

    既然后解析url,那当然也有反解析url,就是把元素串连成一个url

    1from urllib import parse

    2# 将列表元素拼接成url

    3url = ['http', 'www', 'baidu', 'com', 'dfdf', 'eddffa'] # 这里至少需要6个元素(我乱写的,请忽视)

    4print(parse.urlunparse(url))

    5# 下面是结果6http://www/baidu;com?dfdf#eddffa

    urlparse()接收一个列表的参数,而且列表的长度是有要求的,是必须六个参数以上,要不会抛出异常

    1Traceback (most recent call last):

    2 File "E:/anaconda/python_project/python

    3_spider/urllib_test.py", line 107, in

    3 print(parse.urlunparse(url))

    4 File "E:\anaconda\lib\urllib\parse.py", line 4

    54, in urlunparse

    5 _coerce_args(*components))

    6ValueError: not enough values to unpack (expected

    7, got 6)

    urllib.parse.urljoin():这个是将第二个参数的url缺少的部分用第一个参数的url补齐

    1# 连接两个参数的url, 将第二个参数中缺的部分用第一个参数的补齐2print(parse.urljoin('https://movie.douban.com/', 'index'))

    3print(parse.urljoin('https://movie.douban.com/', 'https://accounts.douban.com/login'))

    4# 下面是结果

    5https://movie.douban.com/index6https://accounts.douban.com/login

    urllib.parse.urlencode():这个方法是将字典类型的参数转为请求为get方式的字符串

    1data = {'name': 'sergiojuue', 'sex': 'boy'}

    2data = parse.urlencode(data)

    3print('https://accounts.douban.com/login'+data)

    4# 下面是结果

    5https://accounts.douban.com/loginname=sergiojuue&sex=boy4结语

    还有个urllib.robotparse库少用,就不说了,留给以后需要再去查文档吧。

    上面的只是我在学习过程中的总结,如果有什么错误的话,欢迎在留言区指出,还有就是需要查看更多用法的请查看文档https://docs.python.org/3/library/urllib.html

    需要代码的可以去我的github上面fork,给个star也行!

    github:https://github.com/SergioJune/gongzhonghao_code/blob/master/python3_spider/urllib_test.py

    学习过程中看的大多是崔庆才大佬的视频:https://edu.hellobi.com/course/157

    天善智能学院超值svip,包含商业智能BI、人工智能、业务&求职、大数据&R&Pyhton等十五套课程任选八套,自由搭配,另享全场六折优惠价,超高性价比,限时火爆优惠抢购中戳:https://www.hellobi.com/svip

    相关文章

      网友评论

        本文标题:Python爬虫常用库之urllib详解

        本文链接:https://www.haomeiwen.com/subject/kojihftx.html