urllib详解

urllib是python中请求url链接的标准库,主要包含以下几个模块

  • urllib.request:用于打开和阅读URL
  • urllib.error:包含由引发的异常urllib.request
  • urllib.parse:用于解析URL
  • urllib.robotparser:用于解析robot.txt文件

urllib.request.urlopen()

  • 模块定义了有助于在复杂环境中打开URL(主要是HTTP)的函数和类-基本身份验证和摘要身份验证,重构定向,Cookie等。
  • 语法结构
urllib.request.urlopen(url,data = None[ timeout,] *,cafile = None,capath = None,cadefault = False,context = None
  • 语法详解
    • url:传入的对象可以是url也可以是一个request的对象
    	#传入的对象是url
    	# 设置一个url对象
    	url = "www.baidu.com"
    	#发送请求,打开url
    	urllib.request.urlopen(url)
    	```
    	```puthon
    	#传入的对象是request
    	url = "www.baidu.com"
    	#将url对象转换成request对象
    	req = urllib.request.Request(url)
    	#发送请求,打开url
    	urllib.request.urlopen(url)
    
    • data:data必须是一个直接要发送搭服务器的其他数据的对象,如果没有data数据的话可以为None,也可以不写
    • timeout:以秒为单位制定用于组织链接尝试之类的操作超时
  • urllib.openurl:返回对象的方法
      # 设置一个url对象
      url = "www.baidu.com"
      #发送请求,打开url
      up = urllib.request.urlopen(url)
      print(type(up))
      
      #返回对象
    >>> <class 'http.client.HTTPResponse'>
    

上面我们可以看出返回的对象是HTTPResponse类型的,那我们就一起来看一下HTTPResponse类的方法

- HTTPResponse.read():读取并返回响应主体
- HTTPResponse.readinto(b ):将响应主体的下一个len(b)字节读取到缓冲区b中。返回读取的字节数。
- HTTPResponse.getheader(name,default = None ):返回标头名称的值;如果没有标头匹配名称,则返回默认值。如果有一个以上的标题名为名称,返回全部由加盟值“”。如果'default'是除单个字符串之外的任何可迭代对象,则类似地返回其元素并以逗号连接。
- HTTPResponse.getheaders():返回(头,值)元组的列表。
- HTTPResponse.fileno():返回fileno基础套接字的。
- HTTPResponse.status :服务器返回的状态码。
- HTTPResponse.closed():是True流是否关闭。
- info():返回返回HTTPMessage对象,表示远程服务器返回的头信息
- getcode():返回Http状态码。如果是http请求,200请求成功完成 ; 404网址未找到,与HTTPResponse.status功能一样
- geturl():返回请求的url
  • 发送GET请求:
    from urllib import request
    response = request.urlopen('https://www.baidu.com')
    print(response.read().decode())
    
  • 发送post请求
    from urllib import reuqest
    response = 	request.urlopen('http://httpbin.org/post', data=b'word=hello')
    print(response.read().decode())   #decode()解码
    
    • 我们已经知道在讲urlopen中传入一个网址的时候他就会主动的去访问目标的网址,会返回一个HTTPResponse类型的对象,那么我们是怎么知道我们发送的get请求和post请求呢?下面我们一起来看一下
        def get_method(self):
        """Return a string indicating the HTTP request method."""
        default_method = "POST" if self.data is not None else "GET"
        return getattr(self, 'method', default_method)
    
    • 这个是源码中的一个方法,根据代码我们得知如果data是不为空的话,就是post请求,否则就是get请求
  • urllib.request.Request
    • 上面的urllib是可对网页发起请求,在我们实际的爬虫应用中,如果频繁的访问一个网页,网站就会识别我们是不是爬虫,这个时候我们就要利用Request来伪装我们的请求头
    urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
    
    参数 解析
    url 发起请求的url
    data data必须是一个直接要发送搭服务器的其他数据的对象,如果没有data数据的话可以为None,也可以不写
    headers headers是一个字典类型,是请求头。可以在构造请求时通过headers参数直接构造,也可以通过调用请求实例的add_header()方法添加。可以通过请求头伪装浏览器,默认User-Agent是Python-urllib。要伪装火狐浏览器,可以设置User-Agent为Mozilla/5.0 (x11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11
    origin_req_host 指定请求方的host名称或者ip地址
    unverifiable 设置网页是否需要验证,默认是False,这个参数一般也不用设置。
    method method是一个字符串,用来指定请求使用的方法,比如GET,POST和PUT等。
  • 案例:静态添加请求头
#创建一个url
url = "www.baidu.com"
#创建一个请求头
headers = {
	"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36"
}
#利用request.Request返回一个request对象
requ = request.Request(url,headers=header)
#向网站发出请求
res = request.urlopen(requ)
  • 案例:动态添加请求头
#创建一个url
url = "www.baidu.com"
#利用request.Request返回一个request对象
requ = request.Request(url)
#利用add_header方法动态加入请求头
requ.add_header("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36") 
res = request.urlopen(requ)

代理的使用:proxyHandle类

最常见的反扒技术之一就是通过客户端的IP来判断是否是爬虫,如果同一个IP在短时间内大量的访问服务器的不同界面,那么极有可能是爬虫,如果服务器认为是爬虫那么就会将IP封禁,这样爬虫就无法访问服务器的任何资源了
在urlopen()中并没有给我们定义设置ip的参数,我们观察urlopen的源码可以发现这个urlopen的方法体实际返回的是一个opener.open()

    global _opener
    if cafile or capath or cadefault:
        import warnings
        warnings.warn("cafile, capath and cadefault are deprecated, use a "
                      "custom context instead.", DeprecationWarning, 2)
        if context is not None:
            raise ValueError(
                "You can't pass both context and any of cafile, capath, and "
                "cadefault"
            )
        if not _have_ssl:
            raise ValueError('SSL support not available')
        context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH,
                                             cafile=cafile,
                                             capath=capath)
        https_handler = HTTPSHandler(context=context)
        opener = build_opener(https_handler)
    elif context:
        https_handler = HTTPSHandler(context=context)
        opener = build_opener(https_handler)
    elif _opener is None:
        _opener = opener = build_opener()
    else:
        opener = _opener
    return opener.open(url, data, timeout)

观察上面的源码发现opener对象是由bulid_opener()创建的,而bulid_opener里面的参数是HTTPSHandler类型,那我们就可以得知open()对象是传入HTTPHandler类型构建出来的,那么我们也可以构建自己的opener,下面我们来详细看一下是怎么样构建可以加入ip的opener,创建加入ip的opener我们需要用到ProxyHandler()


#创建一个链接
url = "https://space.bilibili.com/"
#创建一个代理
proxy = {
    "HTTP":"124.239.216.14:2060"
}
# 创建一个代理的处理器
proxy_handler = request.ProxyHandler(proxy)
#创建自己的opener
opener = request.build_opener(proxy_handler)
#使用我们自己的opener来请求网址
w = opener.open(url).read().decode("utf-8")

Cookie

我们再爬虫的过程中会碰到有登录的问题,那么cookie就是网站为了辨别用户身份,进行session跟踪而储存在用户本地终端上的数据,有些网站是必须登录之后才能爬取页面,那么我们就能运用我们的urlib库保存我们登录的cookie,然后再住区其他页面就达到目的了,接下来我们来看一下我们是怎么样利用cookie来发送请求的
from urllib import request,parse
from http import cookiejar



#创建一个方法登录药智网
def login_Yaozhi(username,pwd):

    # 创建一个网址
    url = "https://www.yaozh.com/login/"

    # 创建一个请求头
    header = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36"
    }
    # 创建登录的cookie
    cookie = {
        "username": username,
        "pwd" : pwd,
        "formhash" : "35D0E251E2",
        "backurl" : "https%3A%2F%2Fwww.yaozh.com%2F"
    }
    cook_str = parse.urlencode(cookie).encode("utf-8")

    #创建cookjar
    cook_cookiejar = cookiejar.CookieJar()

    #创建一个cookie的处理器
    cook_hander = request.HTTPCookieProcessor(cook_cookiejar)

    #根据处理器生成opener
    cook_opener = request.build_opener(cook_hander)

    # 创建一个接受请求头的Request对下个
    header_request = request.Request(url, headers=header,data=cook_str)
    #利用opener向网站发起请求,如果请求成功就保存cookie

    cook_opener.open(header_request,)

    #带着cookie访问登录成功的页面
    url_suss = "https://www.yaozh.com/"

    #创建一个访问成功链接的reque
    request_suss = request.Request(url_suss,headers=header)

    #向成功的页面发起请求
    result_suss = cook_opener.open(request_suss)
    #将请求到的数据进行转码
    decode_result_suss = result_suss.read().decode("utf-8")
    with open("login_suss.html","w",encoding="utf-8")as f:
        f.write(decode_result_suss)

if __name__ == '__main__':
    #让用户输入账号
    username = input("请输入账号:")
    #让用户输入密码
    pwd = input("请输入密码:")
    #调用函数
    login_Yaozhi(username,pwd)

你可能感兴趣的:(爬虫)