urllib3

urllib是一个包含几个模块来处理请求的库。分别是:

    urllib.request 发送http请求

    urllib.error 处理请求过程中,出现的异常。

    urllib.parse 解析url

    urllib.robotparser 解析robots.txt 文件

urllib.request

urllib当中使用最多的模块,涉及请求,响应,浏览器模拟,代理,cookie等功能。

1. 快速请求

urlopen返回对象提供一些基本方法:

read 返回文本数据

info 服务器返回的头信息

getcode 状态码

geturl 请求的url

request.urlopen(url, data=None, timeout=10)

#url:  需要打开的网址

#data:Post提交的数据

#timeout:设置网站的访问超时时间


from urllib import request

import ssl

# 解决某些环境下报<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed

ssl._create_default_https_context = ssl._create_unverified_context

url = 'https://www.jianshu.com'

#返回<http.client.HTTPResponse object at 0x0000000002E34550>

response = request.urlopen(url, data=None, timeout=10)

#直接用urllib.request模块的urlopen()获取页面,page的数据格式为bytes类型,需要decode()解码,转换成str类型。

page = response.read().decode('utf-8')

2.模拟PC浏览器和手机浏览器

需要添加headers头信息,urlopen不支持,需要使用Request

PC

import urllib.request


url = 'https://www.jianshu.com'

# 增加header

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36'

}

request = urllib.request.Request(url,headers=headers)

response = urllib.request.urlopen(request)

#在urllib里面 判断是get请求还是post请求,就是判断是否提交了data参数

print(request.get_method())


>> 输出结果

GET

手机

req = request.Request('http://www.douban.com/')

req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) '

                            'AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')

with request.urlopen(req) as f:

    print('Status:', f.status, f.reason)

    for k, v in f.getheaders():

        print('%s: %s' % (k, v))

    print('Data:', f.read().decode('utf-8'))

3.Cookie的使用

客户端用于记录用户身份,维持登录信息

import http.cookiejar, urllib.request


# 1 创建CookieJar对象

cookie = http.cookiejar.CookieJar()

# 使用HTTPCookieProcessor创建cookie处理器,

handler = urllib.request.HTTPCookieProcessor(cookie)

# 构建opener对象

opener = urllib.request.build_opener(handler)

# 将opener安装为全局

urllib.request.install_opener(opener)

data = urllib.request.urlopen(url)


# 2 保存cookie为文本

import http.cookiejar, urllib.request

filename = "cookie.txt"

# 保存类型有很多种

## 类型1

cookie = http.cookiejar.MozillaCookieJar(filename)

## 类型2

cookie = http.cookiejar.LWPCookieJar(filename)


# 使用相应的方法读取

cookie = http.cookiejar.LWPCookieJar()

cookie.load('cookie.txt',ignore_discard=True,ignore_expires=True)

handler = urllib.request.HTTPCookieProcessor(cookie)

opener = urllib.request.build_opener(handler)

……

4.设置代理

当需要抓取的网站设置了访问限制,这时就需要用到代理来抓取数据。

import urllib.request


url = 'http://httpbin.org/ip'

proxy = {'http':'39.134.108.89:8080','https':'39.134.108.89:8080'}

proxies = urllib.request.ProxyHandler(proxy) # 创建代理处理器

opener = urllib.request.build_opener(proxies,urllib.request.HTTPHandler) # 创建特定的opener对象

urllib.request.install_opener(opener) # 安装全局的opener 把urlopen也变成特定的opener

data = urllib.request.urlopen(url)

print(data.read().decode())

urllib.error

urllib.error可以接收有urllib.request产生的异常。urllib.error中常用的有两个方法,URLError和HTTPError。URLError是OSError的一个子类,

HTTPError是URLError的一个子类,服务器上HTTP的响应会返回一个状态码,根据这个HTTP状态码,我们可以知道我们的访问是否成功。

URLError

URLError产生原因一般是:网络无法连接、服务器不存在等。

例如访问一个不存在的url

import urllib.error

import urllib.request

requset = urllib.request.Request('http://www.usahfkjashfj.com/')

try:

    urllib.request.urlopen(requset).read()

except urllib.error.URLError as e:

    print(e.reason)

else:

    print('success')


>> print结果

[Errno 11004] getaddrinfo failed

HTTPError

HTTPError是URLError的子类,在你利用URLopen方法发出一个请求时,服务器上都会对应一个应答对象response,其中他包含一个数字“状态码”,

例如response是一个重定向,需定位到别的地址获取文档,urllib将对此进行处理。其他不能处理的,URLopen会产生一个HTTPError,对应相应的状态码,

HTTP状态码表示HTTP协议所返回的响应的状态。

from urllib import request, error

    try:

        response = request.urlopen('http://cuiqingcai.com/index.htm')

    except error.URLError as e:

        print(e.reason)


    # 先捕获子类错误

    try:

        response = request.urlopen('http://cuiqingcai.com/index.htm')

    except error.HTTPError as e:

        print(e.reason, e.code, e.headers, sep='\n')

    except error.URLError as e:

        print(e.reason)

    else:

        print('Request Successfully')


>> print结果

Not Found

-------------

Not Found

404

Server: nginx/1.10.3 (Ubuntu)

Date: Thu, 08 Feb 2018 14:45:39 GMT

Content-Type: text/html; charset=UTF-8

Transfer-Encoding: chunked

Connection: close

Vary: Cookie

Expires: Wed, 11 Jan 1984 05:00:00 GMT

urllib.parse

urllib.parse.urljoin 拼接url

基于一个base URL和另一个URL构造一个绝对URL,url必须为一致站点,否则后面参数会覆盖前面的host

print(parse.urljoin('https://www.jianshu.com/xyz','FAQ.html'))

print(parse.urljoin('http://www.baidu.com/about.html','http://www.baidu.com/FAQ.html'))


>>结果

https://www.jianshu.com/FAQ.html

http://www.baidu.com/FAQ.html

urllib.parse.urlencode 字典转字符串

from urllib import request, parse

url = r'https://www.jianshu.com/collections/20f7f4031550/mark_viewed.json'

headers = {

    'User-Agent': r'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',

    'Referer': r'https://www.jianshu.com/c/20f7f4031550?utm_medium=index-collections&utm_source=desktop',

    'Connection': 'keep-alive'

}

data = {

    'uuid': '5a9a30b5-3259-4fa0-ab1f-be647dbeb08a',

}

#Post的数据必须是bytes或者iterable of bytes,不能是str,因此需要进行encode()编码

data = parse.urlencode(data).encode('utf-8')

print(data)

req = request.Request(url, headers=headers, data=data)

page = request.urlopen(req).read()

page = page.decode('utf-8')

print(page)


>>结果

b'uuid=5a9a30b5-3259-4fa0-ab1f-be647dbeb08a'

{"message":"success"}

urllib.parse.quote url编码

urllib.parse.unquote url解码

Url的编码格式采用的是ASCII码,而不是Unicode,比如

http://so.biquge.la/cse/search?s=7138806708853866527&q=%CD%EA%C3%C0%CA%C0%BD%E7

from urllib import parse


x = parse.quote('山西', encoding='gb18030')# encoding='GBK

print(x)  #%C9%BD%CE%F7


city = parse.unquote('%E5%B1%B1%E8%A5%BF',)  # encoding='utf-8'

print(city)  # 山西

urllib3包

Urllib3是一个功能强大,条理清晰,用于HTTP客户端的Python库,许多Python的原生系统已经开始使用urllib3。Urllib3提供了很多python标准库里所没有的重要特性:

1.线程安全

2.连接池

3.客户端SSL/TLS验证

4.文件分部编码上传

5.协助处理重复请求和HTTP重定位

6.支持压缩编码

7.支持HTTP和SOCKS代理

安装:

Urllib3 能通过pip来安装:

$pip install urllib3l

urllib3的使用:

request GET请求

import urllib3

import requests

#  忽略警告:InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised.

requests.packages.urllib3.disable_warnings()

# 一个PoolManager实例来生成请求, 由该实例对象处理与线程池的连接以及线程安全的所有细节

http = urllib3.PoolManager()

# 通过request()方法创建一个请求:

r = http.request('GET', 'http://cuiqingcai.com/')


# 获得html源码,utf-8解码

print(r.data.decode())

request GET请求(添加数据)

header = {

        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36'

    }

    r = http.request('GET',

            'https://www.baidu.com/s?',

            fields={'wd': 'hello'},

            headers=header)


    print(r.data.decode())

post请求

  #你还可以通过request()方法向请求(request)中添加一些其他信息,如:

    header = {

        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36'

    }

    r = http.request('POST',

                    'http://httpbin.org/post',

                    fields={'hello':'world'},

                    headers=header)

    print(r.data.decode())

# 对于POST和PUT请求(request),需要手动对传入数据进行编码,然后加在URL之后:

encode_arg = urllib.parse.urlencode({'arg': '我的'})

print(encode_arg.encode())

r = http.request('POST',

                'http://httpbin.org/post?'+encode_arg,

                headers=header)

# unicode解码


print(r.data.decode('unicode_escape'))

发送json数据

#JSON:在发起请求时,可以通过定义body 参数并定义headers的Content-Type参数来发送一个已经过编译的JSON数据:

import json

data={'attribute':'value'}

encode_data= json.dumps(data).encode()


r = http.request('POST',

                    'http://httpbin.org/post',

                    body=encode_data,

                    headers={'Content-Type':'application/json'}

                )

print(r.data.decode('unicode_escape'))

上传文件

#使用multipart/form-data编码方式上传文件,可以使用和传入Form data数据一样的方法进行,并将文件定义为一个元组的形式     (file_name,file_data):

with open('1.txt','r+',encoding='UTF-8') as f:

    file_read = f.read()


r = http.request('POST',

                'http://httpbin.org/post',

                fields={'filefield':('1.txt', file_read, 'text/plain')

                        })

print(r.data.decode('unicode_escape'))


#二进制文件

with open('websocket.jpg','rb') as f2:

    binary_read = f2.read()


r = http.request('POST',

                'http://httpbin.org/post',

                body=binary_read,

                headers={'Content-Type': 'image/jpeg'})

#

# print(json.loads(r.data.decode('utf-8'))['data'] )

print(r.data.decode('utf-8'))

使用Timeout

#使用timeout,可以控制请求的运行时间。在一些简单的应用中,可以将timeout参数设置为一个浮点数:

r = http.request('POST',

                'http://httpbin.org/post',timeout=3.0)


print(r.data.decode('utf-8'))


#让所有的request都遵循一个timeout,可以将timeout参数定义在PoolManager中:

http = urllib3.PoolManager(timeout=3.0)

对重试和重定向进行控制

#通过设置retries参数对重试进行控制。Urllib3默认进行3次请求重试,并进行3次方向改变。

r = http.request('GET',

                'http://httpbin.org/ip',retries=5)#请求重试的次数为5


print(r.data.decode('utf-8'))

##关闭请求重试(retrying request)及重定向(redirect)只要将retries定义为False即可:

r = http.request('GET',

                'http://httpbin.org/redirect/1',retries=False,redirect=False)

print('d1',r.data.decode('utf-8'))

#关闭重定向(redirect)但保持重试(retrying request),将redirect参数定义为False即可

r = http.request('GET',

                'http://httpbin.org/redirect/1',redirect=False)


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容