Python爬虫1.2 — urllib高级用法教程

综述

本系列文档用于对Python爬虫技术进行简单的教程讲解,巩固自己技术知识的同时,万一一不小心又正好对你有用那就更好了。
Python 版本是3.7.4

上篇文章介绍了urllib的基础使用方法本篇文章就来介绍一下urllib稍微高级一点的用法。

网上有很多的网站想要请求需要设置一些请求头,如果要在请求的时候增加一些请求头,那么就必须使用request.Request类来实现了,比如要增加一个 User-Agent ,增加一个 Referer 头信息等。

通常防止爬虫被反主要有以下几个策略:

  1. 动态设置请求头headers(User-Agent)(随机切换User-Agent,模拟不同用户的浏览器信息)
  2. 使用IP地址池:VPN和代理IP,现在大部分网站都是根据IP来ban的
  3. Cookies
  4. 设置延迟下载(防止访问过于频繁,设置为2秒或更高)要明白爬虫重要的是拿到数据(这个用到time库的time.sleep()方法,在这里不在说明)

设置请求头(urllib.request.Request)

urllib.request.Request是urllib的一个抽象类,用于构造一个http请求对象实例。
request类Request方法常用的内置方法:

  • Request.add_data(data)设置data参数,如果一开始创建的时候没有给data参数,那么可以使用该方法追加data参数;
  • Request.get_method() 返回HTTP请求方法,一般返回GET或是POST;
  • Request.has_data() 查看是否设置了data参数;
  • Request.get_data() 获取data参数的数据;
  • Request.add_header(key, val) 添加头部信息,key为头域名,val为域值;
  • Request.get_full_url() 获取请求的完整url;
  • Request.get_host() 返回请求url的host(主域名);
  • Request.set_proxy(host, type) 设置代理,第一个参数是代理ip和端口,第二个参数是代理类型(http/https)。
  1. 代码示例
    # 导入urllib库
    import urllib.parse
    import urllib.request
    
    # 声明定义请求头
    headers = {
        # 在这个头字典里面可以将你所有需要传递的头添加进来
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
    }
    
    # 向指定的url发送请求,并返回
    post_url = 'https://fanyi.baidu.com/sug'
    # 传入参数
    form_data = {
        'kw': 'honey'
    }
    # 格式化参数
    form_data = urllib.parse.urlencode(form_data).encode()
    # 创建Request类
    req = urllib.request.Request(url=post_url, headers=headers, data=form_data)
    
    # 进行请求,打印结果
    ret = urllib.request.urlopen(req)
    print(ret.read())
  1. 爬虫示例

爬取拉勾网Python职位招聘信息(由于拉勾网进行了防爬,访问其接口需要传递Cookie,本人直接在浏览器复制出来写入到请求头中的)。

    # 引入urllib库
    import urllib.parse
    import urllib.request
    
    # 声明定义请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
        'Referer': 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=',
        'Host': 'www.lagou.com',
        'Origin': 'https://www.lagou.com',
        'X-Requested-With': 'XMLHttpRequest',
        'Cookie': '_ga=GA1.2.1158944803.1554684888; user_trace_token=20190408085447-e8216b55-5998-11e9-8cbc-5254005c3644; LGUID=20190408085447-e8216df3-5998-11e9-8cbc-5254005c3644; JSESSIONID=ABAAABAAAFCAAEG89414A0A463BB593A6FCB8B25161B297; WEBTJ-ID=20190803154150-16c566d76a7a71-0d0261dbc1a413-a7f1a3e-2073600-16c566d76a8664; _gid=GA1.2.646413362.1564818110; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1564818110; LGSID=20190803154149-2746a012-b5c2-11e9-8700-525400f775ce; PRE_UTM=; PRE_HOST=www.baidu.com; PRE_SITE=https%3A%2F%2Fwww.baidu.com%2F; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2F; index_location_city=%E5%85%A8%E5%9B%BD; X_HTTP_TOKEN=7b450c20fc1c8ebb1028184651d95c44e86182119a; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1564818202; _gat=1; LGRID=20190803154322-5e321a85-b5c2-11e9-8700-525400f775ce; TG-TRACK-CODE=index_search; SEARCH_ID=f2eeeba9273a435281d59597e5b8b7ba',
    }
    # 拉钩接口地址
    url = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
    # 接口参数
    data = {
        'first': 'true',
        'pn': '1',
        'kd': 'python'
    }
    from_data = urllib.parse.urlencode(data).encode()
    # 声明定义Request类
    req = urllib.request.Request(url=url, headers=headers, data=from_data)
    # 请求接口,打印结果
    res = urllib.request.urlopen(req)
    print(res.read().decode())

使用代理(urllib.request.ProxyHandle)

很多网站会员检测某一时间内某个IP的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正常人,它就会禁止这个IP访问。所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取。

  1. 基本原理
    代理实际上指的就是代理服务器,它的功能是代理网络用户去取得网络信息。形象地说,它是网络信息的中转站。在我们正常请求一个网站时,其实是发送了请求给Web服务器,Web服务器把响应传回给我们。如果设置了代理服务器,实际上就是在本机和服务器之间搭建了一个桥,此时本机不是直接向Web服务器发起请求,而是向代理服务器发出请求,请求会发送给代理服务器,然后由代理服务器再发送给Web服务器,接着由代理服务器再把Web服务器返回的响应转发给本机。这样我们同样可以正常访问网页,但这个过程中Web服务器识别出的真实IP就不再是我们本机的IP了,就成功实现了IP伪装,这就是代理的基本原理。

  2. 作用

    • 突破自身IP访问限制,访问一些平时不能访问的站点;
    • 提高访问速度;
    • 隐藏真实IP。
  3. 常用的代理

    • 西刺代理 : https://www.xicidaili.com/
    • 快代理 : https://www.kuaidaili.com/
    • 云代理 : http://www.ip3366.net/
  4. 用法示例

        # 引入所需要的库
        import random
        import urllib.request
        
        # 声明定义代理服务器列表
        proxy_list = [
            {"http": "220.184.144.80:8060"},
            {"http": "180.175.170.210:8060"},
            {"http": "116.226.28.17:8060"},
            {"http": "123.123.137.72:8060"},
            {"http": "116.226.31.161:8060"}
        ]
        # 随机选择一个代理
        proxy = random.choice(proxy_list)
        
        # 使用选择的代理构建代理处理器对象
        http_proxy_handler = urllib.request.ProxyHandler(proxy)
        # 通过 urllib.request.build_opener(),创建自定义opener对象
        opener = urllib.request.build_opener(http_proxy_handler)
        # 创建Request对象
        url = 'http://www.baidu.com/s?ie=UTF-8&wd=ip'
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
        }
        req = urllib.request.Request(url=url, headers=headers)
        # 使用opener.open()方法发送请求才使用自定义的代理,而urlopen()则不使用自定义代理
        # 这么写,就是将opener应用到全局,之后所有的,不管是opener.open()还是urlopen()发送请求,都将使用自定义代理
        res = opener.open(req)
        print(res.read().decode())
    

Cookie(urllib.request.HTTPCookieProcessor)

  1. cookie是什么

    在网站中,http请求时无状态的,也就是说即使第一次和服务器链接后并且登陆成功后,第二次请求服务器依然不能知道当前请求是那个用户,cookie的出现就是为了解决这个问题,第一次登陆后服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地,当该用户第二次请求的时候,就会自动把上次请求的cookie数据自动的携带给服务器,服务器通过浏览器携带的cookie数据就能判断当前的用户是那个了。cookie存储的数据有限,不同的浏览器又不同的存储大小,但一般不超过4kb,因此使用cookie只能存储一些小量的数据。(解释比较简单,详细的cookie说明可以看百科介绍)

  2. cookie格式

    Set-Cookie: NAME=VALUE; Expires=DATE; Domain=DOMAIN_NAME; Path=PATH; SECURE
    
    • NAME=VALUE:这是每一个Cookie均必须有的部分。NAME是该Cookie的名称,VALUE是该Cookie的值。在字符串“NAME=VALUE”中,不含分号、逗号和空格等字符;
    • Expires=DATE:Expires变量是一个只写变量,它确定了Cookie有效终止日期。该变量可省,如果缺省时,则Cookie的属性值不会保存在用户的硬盘中,而仅仅保存在内存当中,Cookie文件将随着浏览器的关闭而自动消失;
    • Domain=DOMAIN-NAME:Domain该变量是一个只写变量,它确定了哪些Internet域中的Web服务器可读取浏览器所存取的Cookie,即只有来自这个域的页面才可以使用Cookie中的信息。这项设置是可选的,如果缺省时,设置Cookie的属性值为该Web服务器的域名;
    • Path=PATH:Path属性定义了Web服务器上哪些路径下的页面可获取服务器设置的Cookie;
    • SECURE:在Cookie中标记该变量,表明只有当浏览器的通信协议为加密认证协议时,浏览器才向服务器提交相应的Cookie。当前这种协议只有一种,即为HTTPS。
  3. http.cookiejar

    cookielib一般用于客户端处理HTTP cookie信息,通过它可以从服务器端获取cookie信息,反过来又可以通过它将获取到的cookie发送给服务器。cookielib提供了不同的类来自动处理HTTP的cookie信息,使用比较多的类包括了CookieJar、MozillaCookieJar以及Cookie。

代码使用示例(使用http.cookiejar和urllib.request.HTTPCookieProcessor登陆人人网):


    # 引入所需要的库
    import http.cookiejar
    import urllib.parse
    import urllib.request
    
    # 真实的模拟浏览器,当发送完post请求的时候,将cookie保存到代码中
    # 创建一个cookiejar对象
    cj = http.cookiejar.CookieJar()
    # 通过cookiejar创建一个handler
    handler = urllib.request.HTTPCookieProcessor(cj)
    # 根据handler创建一个opener
    opener = urllib.request.build_opener(handler)
    # 人人网登陆地址
    post_uel = 'http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=2019621044248'
    form_data = {
        'email': '188****7357',  # 这是人人网账号
        'icode': '',
        'origURL': 'http://www.renren.com/home',
        'domain': 'renren.com',
        'key_id': '1',
        'captcha_type': 'web_login',
        'password': '01cb55635986f56265d3b55aaddaa79337d094cb56d6cf7724343a93ad586fe7',
        'rkey': 'd5ff51375d8eb17a011cad5622d835fd',
        'f': 'http%3A%2F%2Fwww.renren.com%2F971686685%2Fprofile'
    }
    # 声明定义header
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
    }
    # 创建Request对象,格式化参数
    req = urllib.request.Request(url=post_uel, headers=headers)
    form_data = urllib.parse.urlencode(form_data).encode()
    # 构造访问
    res = opener.open(req, data=form_data)
    print(res.read().decode())
    print('*' * 50)
    
    # 人人网个人中心地址
    get_url = 'http://www.renren.com/971686685/profile'
    # 创建Request对象
    req1 = urllib.request.Request(url=get_url, headers=headers)
    # 构造访问(自带cookie),打印结果
    res1 = opener.open(req1)
    print(res1.read().decode())

  1. cookie信息的保存
    # 引入所需要的库
    import urllib.request
    from http.cookiejar import MozillaCookieJar
    
    # 声明cookiejar
    cj = MozillaCookieJar('cookie.txt')
    # 创建handler\opener
    handler = urllib.request.HTTPCookieProcessor(cj)
    opener = urllib.request.build_opener(handler)
    # 声明定义url,进行访问
    url = 'http://httpbin.org/cookies/set?wei=weizhihua'
    res = opener.open(url)
    # 保存cookie, ignore_discard 设置为True,将过期的cookie也进行保存
    # 如果在声明cookiejar时没有写入文件保存地址,则在save()函数中需写入文件地址参数
    cj.save(ignore_discard=True)
  1. cookie信息的加载
    import urllib.request
    from http.cookiejar import MozillaCookieJar
    
    # 声明cookiejar
    cj = MozillaCookieJar('cookie.txt')
    # ignore_discard 设置为True,将过期的cookie也加载出来
    cj.load(ignore_discard=True)
    # 打印内容
    for cookie in cj:
        print(cookie)

其他博文链接

发布了154 篇原创文章 · 获赞 404 · 访问量 65万+

猜你喜欢

转载自blog.csdn.net/Zhihua_W/article/details/98477507