• 爬虫1——urllib的使用


    一、什么是爬虫

    1、爬虫Spider的概念

    爬虫用于爬取数据,又称之为数据采集程序。

    爬取的数据来源于网络,网络中的数据可以是由WEB服务器(Nginx/Apache),数据库服务器(MySQL、Redis),索引库(ElastichSearch),大数据(Hbase/Hive),视频/图片库(FTP),云存储(OSS)等提供。

    爬取的数据是公开的,非盈利的。

    2、Python爬虫

    使用Python编写的爬虫脚本(程序)可以完成定时,定量,指定目标(web站点)的数据爬取,主要使用多(单)线程/进程、网络请求库、数据解析、数据存储、任务调度等相关技术。

    Python爬虫工程师,可以完成接口测试,功能性测试,性能测试,集成测试。

    二、爬虫与WEB后端服务之间的关系

    爬虫使用网络请求库,相当于客户端请求,Web后端服务根据请求响应数据。

    爬虫即向Web服务器发起HTTP请求,正确的接收响应数据,然后根据数据的类型(Content-Type)进行数据的解析及存储。

    爬虫程序在发起请求前,需要伪造一个浏览器(User-Agent指定头),然后再向服务器发起请求,响应200的成功率高很多。

    三、Python爬虫技术的相关库

    1、网络请求

    • urllib
    • requests
    • selenium(UI自动测试,动态js渲染)
    • appium(手机APP的爬虫或UI测试)

    2、数据解析

    • re正则
    • xpath
    • bs4
    • json

    3、数据存储

    • pymysql
    • mongodb
    • elasticsearch

    4、多任务

    • 多线程(threading)、线程队列 queue
    • 协程(asynio、gevent/eventlet)

    5、爬虫框架

    • scrapy
    • scrapy-redis分布式(多机爬虫)

    四、常见反爬虫的策略

    • UA(User-Agent)策略
    • 登录限制(Cookie)策略
    • 请求频次(IP代理)策略
    • 验证码(图片-云打码,点触验证、滑块)策略
    • 动态js策略(Selenium/Splash/api接口)策略

    五、爬虫库urllib

    1、urllib.request模块

    1.1、简单请求

    from urllib.request import urlopen
    
    # 发起网络请求
    resp = urlopen("http://www.hao123.com")
    assert resp.code == 200
    print("请求成功")
    # 保存请求的网页
    # f变量接收open()函数返回对象的__enter__()返回的就结果

       with open("hao123.html", "wb") as f: f.write(resp.read())

    urlopen(url, data=None)可以直接发起url请求,如果data不为空时,默认是POST请求,反之为GET请求。

    resp是http.client.HTTPResponse类对象

    1.2、带请求头的请求

    """
    初次使用urllib实现爬虫的数据请求
    urllib.request.urlopen(url)  发起get请求
    urllib.parse.quote()   讲中文进行url编码
    urllib.request.urlretrieve(url, filename)  下载url保存到filename
    """
    
    from urllib.request import urlopen, urlretrieve, Request
    from urllib.parse import quote
    
    import ssl
    ssl._create_default_https_context = ssl._create_unverified_context
    
    def search_baidu(wd='李志'):
        # 网络请求资源接口(url)
        url = 'https://www.baidu.com/s?wd=%s'
    
        # 生成请求对象,封装请求的url和头header
        request = Request(url % quote(wd), headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                          'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36',
            'Cookie': 'PSTM=1577115106; BAIDUID=94178A0C4E70392F8094399EE47D06E8:FG=1; BIDUPSID=66B8977AF3BB990218FACD41E237E148; BDUSS=o2amI1SjlZQUZHOTJiTzZoRWVwN051Z2pOSm5hRm12OGd6YUx4VFRaUmtvbkZlRVFBQUFBJCQAAAAAAAAAAAEAAAAi-ccWaHVpeWljaGFubWlhbgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQVSl5kFUpeMX; BD_UPN=12314753; BD_HOME=1; H_PS_PSSID=30974_1429_21108_30997_30824_30717; delPer=0; BD_CK_SAM=1; PSINO=6; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; COOKIE_SESSION=93270_0_5_4_10_6_0_0_4_3_0_3_93360_0_4_0_1583674230_0_1583674226%7C9%230_2_1577625718%7C1; sug=3; sugstore=0; ORIGIN=0; bdime=0; H_PS_645EC=ee56%2Bh2%2FYYj4EN%2FXrG%2FdO5beNAv52Z9Yz4fZg21AWgMroxtYWtP17XRR1VM'
        })
        response = urlopen(request)
        assert response.code == 200
        print("请求成功")
    
        # 读取响应的数据
        bytes_ = response.read()
        with open('%s.html' % wd, "wb") as file:
            file.write(bytes_)

     2、urllib.parse模块

    此模块有两个核心函数:

    quote()仅对中文字符穿进行url编码

    urlencode()可以针对一个字典中所有的values进行编码,然后转成key=value&key=value字符串。

    from urllib.parse import quote
    from urllib.parse import urlencode
    quote("李志")
    '%E6%9D%8E%E5%BF%97'
    urlencode({"姓名":"李志"})
    '%E5%A7%93%E5%90%8D=%E6%9D%8E%E5%BF%97'

     六、百度翻译的实现

    '''
    应用:百度翻译
    urllib.request.Request
    urllib.request.urlopen()
    urllib.parse.urlencode()
    发起post请求
    '''
    import json
    from urllib.parse import urlencode
    from urllib.request import Request, urlopen
    
    
    url = 'https://fanyi.baidu.com/sug'
    
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
                      '(KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36',
        'x-requested-with': 'XMLHttpRequest',
        'cookie': 'PSTM=1577115106; BAIDUID=94178A0C4E70392F8094399EE47D06E8:FG=1; '
                  'BIDUPSID=66B8977AF3BB990218FACD41E237E148; BDUSS=o2amI1SjlZQUZHOTJiTzZo'
                  'RWVwN051Z2pOSm5hRm12OGd6YUx4VFRaUmtvbkZlRVFBQUFBJCQAAAAAAAAAAAEAAAAi-ccWaHVpeWl'
                  'jaGFubWlhbgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQVSl5kFUpeMX;'
                  ' to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22valu'
                  'e%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; REALTIME_TRANS_SWITCH=1; HISTORY_SWITCH=1;'
                  ' FANYI_WORD_SWITCH=1; SOUND_PREFER_SWITCH=1; SOUND_SPD_SWITCH=1; delPer=0; PSINO=6; '
                  'BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; '
                  'BDRCVFR[-pGxjrCMryR]=mk3SLVN4HKm; H_PS_PSSID=30974_1429_21108_30997_30824; '
                  'Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1581948391,1583753885; '
                  'from_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22'
                  '%7D%2C%7B%22value%22%3A%22dan%22%2C%22text%22%3A%22%u4E39%u9EA6%u8BED%22%7D%2C%7B%2'
                  '2value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; Hm_lpvt_64ecd82404c51e03dc91cb'
                  '9e8c025574=1583753974; __yjsv5_shitong=1.0_7_f938cb5bed75810c7f54daa26e4d74d416c7_300_1583753976124_'
                  '219.145.32.239_2b22827f;yjs_js_security_passport=afa2db6dc7814c5d0875abbf087495d6b1b9b20f_1583753976_js'
    }
    
    
    def fanyi(kw):
        data = {
            'kw': kw
        }
        # Request()中的data参数是byte类型
        # data不为空时,就是post请求
        req = Request(url, data=urlencode(data).encode("utf-8"))
        resp = urlopen(req)
        assert resp.code == 200
        json_data = resp.read()  # byte
        content_encode = resp.getheader("Content-Type")
        content_encode = "utf-8" if content_encode is None else content_encode.split("=")[-1]
        return json.loads(json_data.decode(content_encode))  # loads函数将json字串变为字典
    
    
    if __name__ == '__main__':
        print(fanyi("orange"))

    七、GET请求多个页面

    """
    复杂的get请求,多页面请求下载
    """
    import random
    import time
    from urllib.request import Request, urlopen
    from urllib.parse import urlencode
    
    
    url = "https://www.baidu.com/s?"
    params = {
        'wd': '',
        'pn': 0   # 0, 10, 20, 30...= (n-1)*10
    }
    
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
                      '(KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36',
        'x-requested-with': 'XMLHttpRequest',
        'cookie': 'PSTM=1577115106; BAIDUID=94178A0C4E70392F8094399EE47D06E8:FG=1; '
                  'BIDUPSID=66B8977AF3BB990218FACD41E237E148; BDUSS=o2amI1SjlZQUZHOTJiTzZo'
                  'RWVwN051Z2pOSm5hRm12OGd6YUx4VFRaUmtvbkZlRVFBQUFBJCQAAAAAAAAAAAEAAAAi-ccWaHVpeWl'
                  'jaGFubWlhbgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQVSl5kFUpeMX;'
                  ' to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22valu'
                  'e%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; REALTIME_TRANS_SWITCH=1; HISTORY_SWITCH=1;'
                  ' FANYI_WORD_SWITCH=1; SOUND_PREFER_SWITCH=1; SOUND_SPD_SWITCH=1; delPer=0; PSINO=6; '
                  'BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; '
                  'BDRCVFR[-pGxjrCMryR]=mk3SLVN4HKm; H_PS_PSSID=30974_1429_21108_30997_30824; '
                  'Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1581948391,1583753885; '
                  'from_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22'
                  '%7D%2C%7B%22value%22%3A%22dan%22%2C%22text%22%3A%22%u4E39%u9EA6%u8BED%22%7D%2C%7B%2'
                  '2value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; Hm_lpvt_64ecd82404c51e03dc91cb'
                  '9e8c025574=1583753974; __yjsv5_shitong=1.0_7_f938cb5bed75810c7f54daa26e4d74d416c7_300_1583753976124_'
                  '219.145.32.239_2b22827f;yjs_js_security_passport=afa2db6dc7814c5d0875abbf087495d6b1b9b20f_1583753976_js'
    }
    
    def pages_get(wd):
        params['wd'] = wd
        for page in range(1, 101):
            params['pn'] = (page-1) * 10
    
            page_url = url + urlencode(params)
            resp = urlopen(Request(page_url, headers=headers))
            assert resp.code == 200
            filename = "baidu_pages/%s-%s.html" % (wd, page)
            time.sleep(random.random())
            with open(filename, 'wb') as f:
                bytes_ = resp.read()
                f.write(bytes_)
                print('下载%s页成功' % page)
    
    
    
    if __name__ == '__main__':
        pages_get("李志")

    八、Handler处理器

    request对象不能携带cookie,也不能使用代理,所以引入了Handler处理器、自定义Opener。

    1、步骤

    创建Handler对象

    handler = urllib.request.HTTPHandler()

    创建opener对象

    opener= urllib.request.build_opener(handler)

    创建Request对象

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

    发送Reques请求

    response = opener.open(request)

    九、cookie库

    1、cookie库能干啥?

    自动帮我们保存登陆的cookie信息

    2、cookie库配置

    创建一个CookieJar对象

    from http.cookiejar import CookieJar
    cookie = cookiejar.CookieJar()

    使用cookiejar对象,创建一个handler对象

    handler = urllib.request.HTTPCookieProcessor(cookie)

    使用handler创建一个opener

    opener = urllib.request.build_opener(handler)

    通过opener登录

    handler会自动的保存登录之后的cookie

    import urllib.request
    import http.cookiejar as cookiejar
    
    
    post_url = 'http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=20182122180'
    
    data = {
        'rkey':'1c7df63368df7ce73c234de26178ec11',
        'password':'19870115',
        'origURL':'http://www.renren.com/home',
        'key_id':'1',
        'icode':'',
        'f':'http://www.renren.com/224549540',
        'email':'dqsygcz@126.com',
        'domain':'renren.com',
        'captcha_type':'web_login',
    }
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36',
        'Referer': 'http://www.renren.com/SysHome.do'
    }
    
    # 转换字节
    data = urllib.parse.urlencode(data).encode('utf-8')
    # 定制请求对象
    request = urllib.request.Request(url=post_url, headers=headers, data=data)
    # 创建cookie对象
    cookie = cookiejar.CookieJar()
    # 创建handler对象
    handler = urllib.request.HTTPCookieProcessor(cookie)
    # 创建opener对象
    opener = urllib.request.build_opener(handler)
    # 使用opener对象发送请求
    response = opener.open(request)
    print(response.getcode())

    十、代理服务器

    1、什么是代理服务器

    一种重要的服务器安全功能,它的工作主要在开放系统互联(OSI)模型的会话层,从而起到防火墙的作用

    翻墙,是指绕过相应的IP封锁、内容过滤、域名劫持、流量限制等。

    2、代理的常用功能

    突破自身IP访问限制,访问国外站点。

    访问一些单位或团体内部资源

    提高访问速度,通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。

    隐藏真实IP。

    3、代码配置

    创建Reuqest对象

    创建ProxyHandler对象

    用handler对象创建opener对象

    使用opener.open函数发送请求

    # 创建代理handler对象
    handler = urllib.request.ProxyHandler(proxies={'http':'114.212.80.2:3128'})
    
    # 创建opener 
    opener = urllib.request.build_opener(handler)
    # opener.open 替代 urllib.request.urlopen
    response = opener.open(request)
    
    with open('ipp.html','wb') as fp:
        fp.write(response.read())
  • 相关阅读:
    第一次留下自己的随笔
    NSOperation多线程方式
    NSThread多线程方式
    GCD多线程机制
    GCD创建单例常用的两种方法
    线程锁
    使用KVO模式,设置应用角标数字
    keyChain RSA加密 KVO
    NSURLConnection网络处理和NSURLSession网络处理
    UIAlertView和UIAlertViewController
  • 原文地址:https://www.cnblogs.com/huiyichanmian/p/12445876.html
Copyright © 2020-2023  润新知