爬虫——urllib库的基本使用

HTTP请求方法——urlopen()

需要导入urlib.request模块,利用这个模块可以模拟浏览器的请求发起过程


from urllib import request
response = urllib.request.urlopen('http://www.python.org')
print(response.read().decode('utf-8'))
print(type(response))

使用status和getheader()方法获得获得响应的状态码和头信息

print(response.status)
print(response.getheaders())
dict_response = dict(response.getheaders())
print(dict_response['Server'])

添加data参数

添加data参数时,需要使用bytes方法将参数转化为字节流编码格式的内容。一般data参数以字典的形式初始化,因此需要导入urllib.parse模块,利用urlencode方法将字典参数转化为字符串。若传递了data参数,则请求方式不再是GET,而是POST,以模拟表单形式提交,返回一个JSON形式的数据。

data = bytes(urllib.parse.urlencode({'name': 'germey'}), encoding = 'utf-8')
response = urllib.request.urlopen('http://www.httpbin.org/post', data = data)
print(response.read().decode('utf-8'))

 POST请求返回结果:

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "name": "germey"
  }, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Content-Length": "11", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "www.httpbin.org", 
    "User-Agent": "Python-urllib/3.11", 
    "X-Amzn-Trace-Id": "Root=1-6421af11-046298bc158d6bbe5a8bb3e6"
  }, 
  "json": null, 
  "origin": "114.251.216.165", 
  "url": "http://www.httpbin.org/post"
}

        在URL中传递的参数已经出现在了form中。 

设置超时时间——timeout

         timeout以秒为单位,表示请求响应的时间不能大于这个时间,否则返回错误,可以设置异常处理来解决。

try:
    response = urllib.request.urlopen('http://www.httpbin.org/get', timeout=0.1)
except urllib.error.URLError as e:
    if isinstance(e.reason, socket.timeout):
        print('timeout')

构造Request类发起响应

        urllib.request.Request类中可通过六个参数来构造一个对象,再使用urllib.request.urlopen()发起URL请求。

        url: 用于请求URL,这是必传参数,其他都是可选参数。

        data: 如果要传数据,必须是bytes类型,可以使用urllib.parse模块里的urlencode()方法将其他类型的数据结构转化为字符串型,在使用bytes方法进行编码。

        headers:这是一个字典,即请求头,既可以通过headers参数传递,也可以通过add_header方法传递请求头数据。

        origin_req_host:这是请求方的host名称或者IP地址。

        unverifiable:表示请求是否无法验证,意思是没有足够的权限来接收这个请求的结果,默认取值为False,若为True,则表示没有足够的权限接收请求的结果。

        method:·指示请求的使用方法,例如GET,POST,PUT等。

例如:

url = 'https://www.httpbin.org/post'
headers = {
    'User-Agent': 'Mozillla/4.0 (compatible; MSIE 5.5; Windows NT)',
    'Host': 'www.httpbin.org'
}
dict = {'name':'germey'}
data = bytes(parse.urlencode(dict), encoding='utf-8')
req = request.Request(url = url, data = data, headers = headers, method = 'POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))

返回结果:

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "name": "germey"
  }, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Content-Length": "11", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "www.httpbin.org", 
    "User-Agent": "Mozillla/4.0 (compatible; MSIE 5.5; Windows NT)", 
    "X-Amzn-Trace-Id": "Root=1-6421b2f8-5db08d1a4886ce6f529a71db"
  }, 
  "json": null, 
  "origin": "114.251.216.165", 
  "url": "https://www.httpbin.org/post"
}



         成功设置了data, headers , method。

高级用法

1、HTTPDefaultErrorHandler用于处理HTTP响应错误,所有错误都会抛出HTTPError类型的异常
2、HTTPRedirectHandler用于处理重定向
3、HTTPCookieProcessor用于处理Cookie
4、ProxyHandler用于处理设置代理,代理默认为空
5、HTTPPasswordMgr 用于管理密码,他维护这用户名密码的对照表
6、HTTPBasicAuthHandler用于管理认证,如果一个链接再打开时需要认证,那么可以用这个类解决认证问题

1、验证

        某些网站启用了基本身份验证,即登录验证方式,允许网页浏览器或者其他客户端程序在请求网站时提供用户名和口令形式的身份凭证。

        当爬虫请求这样需要登录验证方式的网页时,可以使用HTTPBasicAuthHandler模块来完成。

例如:

from urllib.request import HTTPBasicAuthHandler,HTTPPasswordMgrWithDefaultRealm, build_opener
from urllib.error import URLError

username = '123'
password = '123'
url = 'https://ssr3.scrape.center/'

p = HTTPPasswordMgrWithDefaultRealm()
p.add_password(None, url, username, password)
auth_handler = HTTPBasicAuthHandler(p)
opener = build_opener(auth_handler)

try:
    result = opener.open(url)
    html = result.read().decode('utf-8')
    print(html)
except URLError as e:
    print(e.reason)

        首先导入HTTPBasicAuthHandler和HTTPPasswordMgrWithDefaultRealm模块,以及build_opener模块。HTTPPasswordMgrWithDefaultRealm实例化一个对象,并将设置的用户名,密码,访问的URL通过add_password()方法加入到p中。

        接着实例化一个HTTPBasicAuthHandler对象名为auth_handler,将HTTPPasswordMgrWithDefaultRealm对象作为参数加入该对象auth_handler中,最后将auth_handler作为参数构造一个build_opener对象,再使用open()方法请求响应。

2、代理

        即代理服务器,伪装一个IP,代理用户取得网络信息,可以理解为网络信息的一个中转站,隐藏真实的IP。

        导入ProxyHandler模块,利用该模块实例化一个HTTP代理对象,其参数是一个字典,键名是一个协议类型,键值是代理连接,设置IP地址和端口号,可以添加多个代理连接。同样使用Opener类中的open方法打开链接。

        

from urllib.request import ProxyHandler
from urllib.error import URLError

proxy_handler = ProxyHandler({
    'http': 'http://127.0.0.1:8080',
    'https': 'https://127.0.0.1:8080'
})

opener = urllib.build_opener(proxy_handler)
try:
    response = opener.open('http://www.python.org')
    print(response.read().decode('utf-8'))
except URLError as e:
    print(e.reason)

3、Cookie 

        要获取一个网站的Cookie,必须声明一个CookieJar对象,在利用HTTPCookieProcessor构建一个Handler,再构建Opener对象利用open方法打开链接,再输出Cookie的条目的名称和值。

import http.cookiejar, urllib.request

cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
for item in cookie:
    print(item.name + '=' + item.value)

获取的Cookie:

BAIDUID=1EC5DDB2F87B20DA0341DA639B143B5F:FG=1
BIDUPSID=1EC5DDB2F87B20DAA5CFAB0ADE1D491D
PSTM=1679931978
H_PS_PSSID=36554_38410_38106_38469_38345_38358_38468_38172_38289_36804_37925_38383_26350_37881
BDSVRTM=0
BD_HOME=1

        将CoojieJar换成MozillaCookieJar,可以生成一个处理与Cookie相关的文件。同样LWPCookieJar同样可以读取和保存Cookie,只是保存的格式MozillaCookieJar不一样,会以LWP(libwww-perl)格式保存。

        以LWPCookieJar为例:

filename = 'cookie.txt'
# MozillaCookieJar处理与Cookie相关的事件,如读取和保存Cookie,可以将Cookie保存成Mozilla型浏览器的Cookie格式
cookie = http.cookiejar.LWPCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)

得到cookie.txt文件:

#LWP-Cookies-2.0
Set-Cookie3: BAIDUID="61982F8EE5478ED497357F44E40242B9:FG=1"; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2024-03-26 15:51:08Z"; comment=bd; version=0
Set-Cookie3: BIDUPSID=61982F8EE5478ED48F8B2C02E055C3BC; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2091-04-14 19:05:15Z"; version=0
Set-Cookie3: PSTM=1679932271; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2091-04-14 19:05:15Z"; version=0
Set-Cookie3: H_PS_PSSID=36549_38406_38469_38368_38400_38467_38174_38289_37927_38383_26350_37881; path="/"; domain=".baidu.com"; path_spec; domain_dot; discard; version=0
Set-Cookie3: BDSVRTM=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0
Set-Cookie3: BD_HOME=1; path="/"; domain="www.baidu.com"; path_spec; discard; version=0

 4、处理异常

        1、URLError

                来自urllib库的error模块,由request模块产生的异常可以由这个异常捕获。

        具有一个reason属性,即返回错误的原因。

        2、HTTPError

                是URLError的子类,专门来处理HTTP请求错误,有三个属性,code:状态码。reason:错误的原因;headers:返回请求头。

由于URLError是HTTPError的父类,则当两个异常一起使用时,可以先捕获子类的异常,再捕获父类的异常。

from urllib.error import URLError, HTTPError
import urllib.request

try:
    response = urllib.request.urlopen('https://cuiqingcai.com/404')
except HTTPError as e:
    print(e.reason, e.code, e.headers, sep='\n')
except URLError as e:
    print(e.reason)
else:
    print("request successfully")

 异常处理:捕获HTTPError异常

Not Found
404
Server: GitHub.com
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin: *
ETag: "63cf03be-247b"
Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'; img-src data:; connect-src 'self'
x-proxy-cache: MISS
X-GitHub-Request-Id: 4CF4:36A3:36D242:3AC283:6421BDF8
Accept-Ranges: bytes
Date: Mon, 27 Mar 2023 16:03:03 GMT
Via: 1.1 varnish
Age: 63
X-Served-By: cache-hkg17927-HKG
X-Cache: HIT
X-Cache-Hits: 1

        Not Foun表示该页面找不到。

        导入超时间timeout类时,设置了时间,可以使用isinstance()方法判断两个对象是否为同一个类,判断异常是否为超时。

        例如:if isinstance(e.reason, socket.timeout) 判断原因是否为请求超时。

猜你喜欢

转载自blog.csdn.net/longhaierwd/article/details/129805973