美文网首页程序员
爬虫小白:02-urllib的使用

爬虫小白:02-urllib的使用

作者: 見贤思齊_ | 来源:发表于2020-03-04 21:05 被阅读0次

    urllib的使用

    一、request模块

    http://httpbin.org 是github的http测试的接口。httpbin.org 这个网站能测试 HTTP 请求和响应的各种信息,比如 cookie、ip、headers 和登录验证等,且支持 GET、POST 等多种方法,对 web 开发和测试很有帮助。

    导入模块:
    1、import urllib
    使用:urllib.request.
    但这样会报错: AttributeError: module 'urllib' has no attribute 'request'
    原因:在python3中request被作为一个模块,而不是方法。
    解决方法:将request作为一个模块,如import urllib.request。

    2、from urllib import request
    requset.

    1、urlopen()方法:是一个简单发送网络请求的方法。它接收一个字符串格式的 url ,它会向传入的 url发送网络请求,然后返回结果。
    参数:
    (1)url='' #字符串格式
    例:
    import urllib
    response =urllib.request.urlopen(url='http://httpbin.org/get')

    (2)data:是可选的,传入它则会发起POST请求,否则默认会发送get请求。data参数是字节 类型、或者类文件对象或可迭代对象。
    import urllib import request
    response = request.urlopen(url='http://httpbin.org/post',
    data=b'username=wsq&password=123')

    用data就是post请求,字节类型,用b''来转换成字节,且data中的数据会作为表单中的数据。

    (3)timeout:设置超时时间,以秒为单位。如果请求超过设置时间,则抛出异常;若没有指定 则用系统默认设置。timeout参数只对 http、https以及ftp连接起作用。
    报错会出现:urllib.error.URLError: <urlopen error timed out>
    from urllib
    response =urllib.request.urlopen(url='http://www.baidu.com',
    timeout=0.1)
    2、Request类:
    解释:利用urlopen()可以发起最基本的请求,但这几个参数不足以构件一个完整的请求,可以利用 Request对象来构建更加完整的请求。
    (1) 请求头添加:
    from urllib import request
    headers={
    'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64rv:73.0) Gecko/20100101 Firefox/73.0"
    } #注意:一定是字典形式。
    req = request.Request(url='http://www.baidu.com',headers = headers)

    reponse = request.urlopen(req)
    Referer:这个涉及防盗链技术,假如爬取一个图片出现403,在请求头里添加上它,大多数都 可以解决。

    (2) 操作Cookie。(但不会用它操作,日后常用request)
    (3) 设置代理:自己写个代理库。(间接请求,保护自己的IP地址)
    (4) 验证:
    ​</pre>

    3、Response对象:
    urllib库中的类或者方法,在发送网络请求后,都会返回一个urllib.response的对象(例如: http.client.HTTPResponse object at ......)
    它包含了请求回来的数据结果。它包含一些属性和方法,供我们处理返回的结果。

    (1)、read():获取响应返回的数据,只能用一次。和文件句柄一样,只能运行一次。#返回的是字节码,decode() 解码成字符串。
    (2)、readline():读取一行。没必要。
    while True:
    data = response.readline()
    if data:
    print(data)
    (3)、info():获取响应头信息。 print(response.info())
    (4)、geturl():获取访问的url。 print(response.geturl())
    (5)、getcode() :返回状态码。 print(response.getcode())</pre>

    二、parse模块

    parse模块是一个工具模块,提供了需要对url处理的方法,用于解析url。
    注意: url中只能包含ascii字符,在实际操作过程中,get请求通过url传递的参数中会有大量特殊字符 (非ascii字符),例如汉字,那么就需要进行url编码。(一个中文用UTF-8有3个字节。)
    导包:from urllib import parse(import urllib不行问题同上)

    方法:
    1、parse.quote():编码
    例: url = 'http://httpbin.org/get?username={}'
    result = url.format(parse.quote('思齊')) #format方法别忘了
    print(result)

    结果为: http://httpbin.org/get?username=%E6%80%9D%E9%BD%8A

    2、parse.unquote():反编码,看看具体参数是什么。
    例1:
    print(parse.unquote(result))

    结果为: http://httpbin.org/get?username=思齊

    3、parse.urlencode():在发送请求时,往往会需要传递很多的参数,如果用字符串拼接会很麻 烦,该方法就是用来拼接url参数的。
    例1: args = {'username':'思齊','password':'小淘'}
    res = parse.urlencode(args) #注意字典形式
    print(res)

    结果为: username=%E6%80%9D%E9%BD%8A&pd=123

    例2:
    args = {'username':'思齊','pd':'123'}
    result = 'http://httpbin.org/get?{}'.format(parse.urlencode(args))
    print(res)

    结果为: http://httpbin.org/get?username=%E6%80%9D%E9%BD%8A&pd=123

    注:url中规定多个参数 & 连接。

    4、parse.parse_qs(): 和parse.urlencode()是相反的,将它转会字典。
    例:print(parse.parse_qs(res))

    结果为:{'username': ['思齊'], 'pd': ['123']}

    {'http://httpbin.org/get?username': ['思齊'], 'pd': ['123']}

    错误信息:
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) #当出现这种错误时就是参数用的不是ascii码。</pre>

    三、error模块

    error模块主要负责异常处理,如果请求出现错误,我们可以用error模块进行处理,该模块主要包含
    URLError和HTTPError

    导包:from urllib import error
    1.URLError:是error模块的基类,由request模块产生的的异常都可以用这个类来处理。

    2.HTTPError:是的子类,主要包含三个属性:code:请求的状态码、reason:错误的原因、headers: 响应的报头。
    例:
    try:
    request.urlopen('https://www.jianshu.com')#不是合法的用户会被 ban。
    except error.HTTPError as e:
    print(e.code)
    print(e.reason)
    print(e.headers)</pre>

    四、robotparse模块

    robotparse模块主要负责处理爬虫协议文件,robots.txt的文件。
    导包:from urllib import robotparse
    https://www.amazon.cn/robots.txt #亚马逊中国的爬虫协议,如图1</pre>

    urllib3的使用

    介绍:是一个基于python3的功能强大,友好的http客户端。
    保证线程安全(不需考虑锁的问题),连接池保持(而不向之前的一样连一下关一下),支持重复请求、重定位,保证代码百分百被使用。

    导包:import urllib3

    (1)构造请求(request):
    1.实例化一个PoolManager对象构造请求,这个实例对象处理了连接池和线程安全的所有细节,所以我们不用自行处 理。
    例: http = urllib3.PoolManager()
    在这里我出现了一个错误,如下:
    AttributeError: module 'urllib3的使用' has no attribute 'PoolManager',我出现 这个原因是py文件所在的文件夹命名为urllib3。

    2.用request()方法发送请求,可以用request()方法发送任意请求,GET POST....
    第一个参数是何种类型的请求;第二个参数是请求的网站。

    例1:发送get请求
    response = http.request('GET','http://httpbin.org/get ',b'User- Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64rv:73.0) Gecko/20100101 Firefox/73.0')
    此处传的二进制数据报错

    例2:发送POST请求
    response = http.request('POST','http://httpbin.org/post',
    fields={'hello':'world'})

    3.请求传入数据(data):

    • Headers:加入请求头
      在request方法中添加字典格式的headers参数来指定请求头。
      例:http = urllib3.PoolManager()
      response = http.request('POST','http://httpbin.org/get ',
      headers={'key':'value'})

    • Query parameters(字符串参数):
      *get,head,delete请求,可通过提供字典类型的参数fields来添加查询参数。(复习一 下:在urllib中我们通过parse.quote()编码这里只需提供fields参数即可)
      例:http = urllib3.PoolManager()
      response = http.request('get','http://httpbin.org/get ',
      fields={'key':'value'})

    *对于post,put请求,如果需要查询参数,需要通过url编码将参数编码正确格式再拼接到url中。
    例: 如图1、2、3
    import urllib3
    import urllib.parse import urlencode
    import json
    http = urllib3.PoolManager()
    args = {'username':'思齊','password':'小淘'}

    方法一:

    result = urlencode(args)
    url = 'http://httpbin.org/post?' + result #字符串拼接

    方法二:

    url1 = 'http://httpbin.org/post?{}'
    url1 = url.format(parse.urlencode(args))


    response = http.request('POST',url)
    print(json.loads(response.data.decode('utf-8')))

    *form data(表单数据):
    对于post,put,需要提供字典类型的参数fields来传递form表单数据。
    response = http.request('post','http://httpbin.org/get ',
    fields={'key':'value'})

    *json数据
    当我们需要发送json数据时,我们需要在request方法中传入编码后的二进制数据类型的body参数,并 指定Content-Type的请求头。

    *文件上传(通常不用这个上传)
    对于文件上传,我们可以模仿浏览器表单的方式

    对于二进制数据上传,我们用指定body的方式,并设置Content-Type的请求头。

    *注意:get,head,delete请求中提供fields参数会自动拼接到url中,而对post,put请求中你提供的 fields参数会填写到form表单中,若你想拼接到url中只能主动的使用字符串拼接的方法。
    (2)http响应对象提供 status、data、headers等属性
    例1:
    import urllib3
    http = urllib3.PoolManager()
    response = http.request('get','http://httpbin.org/get')
    print(type(response))#返回的是<class 'urllib3.response.HTTPResponse'>

    也就是http响应对象

    print(response.data) #返回的是二进制数据
    print(response.headers)#返回的是<class 'urllib3._collections.HTTPHeaderDict'>

    字典形式,因此可以通过键名看键值

    print(response.status)

    (3)返回的是 json格式数据 可以通过json模块,loads为字典数据类型。
    例:
    import urllib3
    import json
    http = urllib3.PoolManager()
    response = http.request('get','http://httpbin.org/ip')
    print(json.load(response.data.decode('utf-8')))

    // response.data.decode('utf-8') 解码成字符串。

    (4)返回的数据都是字节类型,对于大量的数据我们通过stream(流)来处理更好,也可以当作一个文件对象来处理。
    例1:流
    import urllib3
    http = urllib3.PoolManager()
    response = http.request('get','http://httpbin.org/bytes/1024',
    preload_content = False)
    for i in response.stream(32): #一点点读对内存好,下图片就可以用这种方法
    print(i)

    例2:文件对象
    import urllib3
    http = urllib3.PoolManager()
    response = http.request('get','http://httpbin.org/bytes/1024', preload_content = False)
    for line in response: #比如说大文件可能5G大小,不能一次性回来,一批一批的回来
    print(line)

    (5)代理
    例1:import urllib3
    proxy = urllib3.ProxyManager('http://ip:端口号')
    //用这个ip来帮助你来向某网站发送请求,保护了你自己的ip地址不被暴露。

    response = proxy.request('get','http://httpbin.org/ip')
    //http://httpbin.org/ip 查看请求的ip地址

    print(response.data)

    //遇到如下错误urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='115.210.79.22', port=8118): Max retries exceeded with url: http://httpbin.org/ip (Caused by ProxyError('Cannot connect to proxy.', NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f7ed4c1aef0>: Failed to establish a new connection: [Errno 111] Connection refused',))) 如果是初次使用代理,以上三 种错误出现的原因基本是1.端口错误2.代理类型不正确。 明确的一点是访问https站点,要用https类型的代理。http同理。(当然我找的是免费代理,可能不好用。)

    相关文章

      网友评论

        本文标题:爬虫小白:02-urllib的使用

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