zoukankan      html  css  js  c++  java
  • 爬虫 多任务异步爬虫 aiohttp selenim

    协程

    # # 协程
    # import asyncio
    # import time
    #
    # # 创建一个协程对象
    # #定义一个特殊函数,特殊:调用后返回一个协程对象,且函数内部的实现语句不会立即执行
    # async def request(url):
    #     print("start",url)
    #     time.sleep(1)
    #     print("end",url)
    #
    # # 创建任务对象,对协程对象封装
    # a=request('aaa')
    #
    # task=asyncio.ensure_future(a)
    #
    #
    # # 创建一个事件循环对象
    # loop=asyncio.get_event_loop()
    # # 将任务对象注册到该对象中,并启动事件循环
    # loop.run_until_complete(task)
    
    
    # # 任务对象绑定回调
    # import asyncio
    # import time
    #
    # async def request(url):
    #     print("start",url)
    #     time.sleep(1)
    #     print("end",url)
    #     return url
    #
    # # 回调函数
    #
    # #定义一个任务对象的回调函数
    # #task参数表示的就是该函数被绑定的那个任务对象
    # def task_back(task):
    #     print("i am tadk_back")
    #     print(task.result())
    #
    # # 任务对象
    # a=request("www.1.com")
    # task=asyncio.ensure_future(a)
    # # 回调
    # task.add_done_callback(task_back)
    #
    # loop=asyncio.get_event_loop()
    # loop.run_until_complete(task)
    
    # # 多任务异步协程
    # import asyncio
    # import time
    #
    # start=time.time()
    # async def request(url):
    #     print("start",url)
    #      # time模块是不支持异步
    #     # time.sleep(2)
    #
    #     # 阻塞操作必须使用await关键字进行挂起
    #     await asyncio.sleep(2)
    #
    #
    #
    #     print("end",url)
    #     return url
    #
    #
    # def task_back(task):
    #     print("i am task_back")
    #     print(task.result())
    #
    # urls=[
    #     'www.1.com',
    #     'www.2.com',
    #     'www.3.com',
    # ]
    #
    # # #多任务列表:存放多个任务对象
    # tasks=[]
    # for url in urls:
    #     a=request(url)
    #     task=asyncio.ensure_future(a)
    #
    #     task.add_done_callback(task_back)
    #     # 将多个任务对象装在到一个任务列表中
    #     tasks.append(task)
    #
    # loop=asyncio.get_event_loop()
    # #多任务注册
    # # wait 就是将任务列表中的任务对象挂起
    # loop.run_until_complete(asyncio.wait(tasks))
    #
    # print(time.time()-start)

    多任务异步爬虫测试

    from flask import Flask
    import time
    app=Flask(__name__)
    
    @app.route("/aaa")
    def aaa():
        time.sleep(2)
        return "aaa"
    
    @app.route("/bbb")
    def bbb():
        time.sleep(2)
        return "bbb"
    
    @app.route("/ccc")
    def ccc():
        time.sleep(2)
        return "ccc"
    
    if __name__ == '__main__':
        app.run()
    #多任务异步爬虫测试
    
    # 测试发现  requests 不支持异步操作
    import asyncio
    import time
    import requests
    start=time.time()
    
    # 协程对象
    async def request(url):
        page_text=requests.get(url).text
        return page_text
    
    
    # 回调函数
    def task_back(task):
        print("callback函数")
        print(task.result())
    
    urls=[
        'http://127.0.0.1:5000/aaa',
        'http://127.0.0.1:5000/bbb',
        'http://127.0.0.1:5000/ccc',
    ]
    
    tasks=[]
    for url in urls:
        c=request(url)
        task=asyncio.ensure_future(c)
    
        task.add_done_callback(task_back)
        tasks.append(task)
    
    loop=asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    
    print(time.time()-start)
    
    # 测试失败

    aiohttp

    # - aiohttp模块:是一个支持异步的网络请求模块
    #     - pip install aiohttp
    
    # 在特殊函数内部不可以出现不支持异步模块相关的代码
    # 简单的基本架构:
    # async def request(url):
    #    with aiohttp.ClientSession() as s:
    #        #s.get/post和requests中的get/post用法几乎一样:url,headers,data/prames
    #        #在s.get中如果使用代理操作:proxy="http://ip:port"
    #        with s.get(url) as response:
    #            #获取字符串形式的响应数据:response.text()
    #            #获取byte类型的:response.read()
    #            page_text = response.text()
    #            return page_text
    # 在当前架构的基础上补充细节即可
    # 细节1:在每一个with前加上async关键字
    # 细节2:在get方法前和response.text()前加上await关键字进行手动挂起操作
    
    
    import aiohttp
    import time
    import asyncio
    
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
    }
    
    start = time.time()
    
    
    # 协程对象
    async def request(url):
        async with aiohttp.ClientSession() as s:
            async with await s.get(url, headers=headers) as response:
                page_text = await  response.text()
                return page_text
    
    
    # 回调函数
    def parse(task):
        print("回调函数测试")
        print(task.result())
    
    
    urls = [
        'http://127.0.0.1:5000/aaa',
        'http://127.0.0.1:5000/bbb',
        'http://127.0.0.1:5000/ccc',
    ]
    
    # 测试最大异步任务量 最大任务量约为500
    # urls=[]
    # for i in range(500):
    #     urls.append('http://127.0.0.1:5000/ccc')
    
    
    tasks = []
    
    for url in urls:
        # 任务对象
        c=request(url)
        task=asyncio.ensure_future(c)
    
        task.add_done_callback(parse)
    
        tasks.append(task)
    
    loop=asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    
    print(time.time()-start)
    import aiohttp
    import asyncio
    import time
    import requests
    from lxml import etree
    headers={
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
    }
    # 采用requsts 获得数据
    # all_titles=[]
    # url='http://wz.sun0769.com/index.php/question/questionType?type=4&page=%d'
    # for page in range(2):
    #     page=page*30
    #     new_url=format(url%page)
    #
    #     response=requests.get(url=new_url,headers=headers)
    #     page_text=response.text
    #     tree=etree.HTML(page_text)
    #     tr_list=tree.xpath('//*[@id="morelist"]/div/table[2]//tr/td/table//tr')
    #     for tr in tr_list:
    #         title=tr.xpath('./td[2]/a[2]/text()')[0].encode("iso-8859-1").decode("gbk")
    #         all_titles.append(title)
    #     print(all_titles)
    
    # 协程对象
    
    # 目前出现问题 'gb2312' codec can't decode byte 0x85 in position 26952: illegal multibyte sequence
    async def request(url):
        async with aiohttp.ClientSession() as s:
            async with await s.get(url=url,headers=headers) as response:
                page_text = await response.text()
                return page_text
    
    start=time.time()
    
    all_titles = []
    # 回调函数
    def parse(task):
        page_text=task.result()
        # page_text=page_text.encode("iso-8859-1").decode("gbk")
        page_text=page_text.encode("gb2312").decode("gbk")
        tree = etree.HTML(page_text)
        tr_list = tree.xpath('//*[@id="morelist"]/div/table[2]//tr/td/table//tr')
        for tr in tr_list:
            title = tr.xpath('./td[2]/a[2]/text()')[0]
            all_titles.append(title)
        print(all_titles)
    
    
    # 请求列表
    urls=[]
    url='http://wz.sun0769.com/index.php/question/questionType?type=4&page=%d'
    for page in range(1):
        page=page*30
        new_url=format(url%page)
        urls.append(new_url)
    
    tasks=[]
    for url in urls:
        c=request(url)
        task=asyncio.ensure_future(c)
    
        task.add_done_callback(parse)
    
        tasks.append(task)
    
    loop=asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    案例

    selenim

    selenium模块的使用
    - 概念:就是一个基于浏览器自动化的模块。
    - selenium和爬虫之间的关联
    - 很便捷的捕获动态加载的数据 - 可见即可得
    - 实现模拟登陆
    - 使用
    - 环境的安装:
    - pip install selenium
    - 下载一个浏览器的驱动程序
    - 谷歌驱动下载:http://chromedriver.storage.googleapis.com/index.html
    - 驱动程序和浏览器版本的映射关系:http://blog.csdn.net/huilan_same/article/details/51896672
    - 创建某一款一个浏览器对象

    - 动作链
    - 如果想要触发一系列连续的行为动作

    记得放置谷歌驱动

    测试selenim

    from selenium import webdriver
    from time import sleep
    
    # 后面是你的浏览器驱动位置,记得前面加r'','r'是防止字符转义的
    driver = webdriver.Chrome(r'chromedriver.exe')
    # 用get打开百度页面
    driver.get("http://www.baidu.com")
    # 查找页面的“设置”选项,并进行点击
    driver.find_elements_by_link_text('设置')[0].click()
    sleep(2)
    # # 打开设置后找到“搜索设置”选项,设置为每页显示50条
    driver.find_elements_by_link_text('搜索设置')[0].click()
    sleep(2)
    
    # 选中每页显示50条
    m = driver.find_element_by_id('nr')
    sleep(2)
    m.find_element_by_xpath('//*[@id="nr"]/option[3]').click()
    m.find_element_by_xpath('.//option[3]').click()
    sleep(2)
    
    # 点击保存设置
    driver.find_elements_by_class_name("prefpanelgo")[0].click()
    sleep(2)
    
    # 处理弹出的警告页面   确定accept() 和 取消dismiss()
    driver.switch_to_alert().accept()
    sleep(2)
    # 找到百度的输入框,并输入 美女
    driver.find_element_by_id('kw').send_keys('美女')
    sleep(2)
    # 点击搜索按钮
    driver.find_element_by_id('su').click()
    sleep(2)
    # 在打开的页面中找到“Selenium - 开源中国社区”,并打开这个页面
    driver.find_elements_by_link_text('美女_百度图片')[0].click()
    sleep(3)
    
    # 关闭浏览器
    driver.quit()

    使用selenim

    from selenium import  webdriver
    from time import sleep
    
    # 指定浏览器驱动位置,记得前面加r'','r'是防止字符转义的
    bro=webdriver.Chrome(executable_path=r'chromedriver.exe')
    
    # 发起请求
    bro.get("https://www.jd.com/")
    #在搜索框中搜索商品
    
    #可以使用find系列的方法进行标签定位
    
    search_input=bro.find_element_by_xpath('//*[@id="key"]')
    #想搜索框中写入商品名称
    search_input.send_keys('iphone')
    sleep(2)
    # 点击搜索按钮
    btn=bro.find_element_by_xpath('//*[@id="search"]/div/div[2]/button')
    btn.click()
    sleep(2)
    
    # 执行js 让鼠标滚轮向下滑动
    bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
    
    page_text=bro.page_source
    
    with open('./jingdong.html','w',encoding='utf-8') as fp:
        fp.write(page_text)
    sleep(1)
    
    bro.quit()

    动作链

    from selenium import webdriver
    # 动作链
    from selenium.webdriver import ActionChains
    
    from time import sleep
    
    # 指定浏览器驱动位置,记得前面加r'','r'是防止字符转义的
    bro=webdriver.Chrome(executable_path=r'chromedriver.exe')
    
    # 发起请求
    # 选择 测试  https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable
    bro.get("https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable")
    
    # 定位要拖动的标签
    #定位的标签是存在于iframe的子页面中,如果直接使用find做定位,是定位不到的
    # target_ele=bro.find_element_by_id('draggable')
    # print(target_ele)
    
    # 若要定位iframe 中的子页面中的标签必须进行如下操作
    
    bro.switch_to.frame('iframeResult')
    target_ele=bro.find_element_by_id('draggable')
    
    # 基于动作链实现滑动操作
    action=ActionChains(bro)
    # 点击并长按
    action.click_and_hold(target_ele)
    
    for i in range(5):
        # perform()#表示立即执行动作连指定好的动作
        action.move_by_offset(17,0).perform()
        sleep(0.5)
    
    action.release()
    sleep(2)
    bro.close()

    总结

    1.什么是代理?代理和爬虫之间的关联是什么?
    
    2.在requests的get和post方法常用的参数有哪些?分别有什么作用?(四个参数)
        - url headers parmas/data proxies
    3.在爬虫中如何处理cookie相关的操作?(两种方式)
        - 手动
        - 自动
    4.什么是动态请求参数?通常情况下如何捕获动态请求参数呢?
        - 每次请求都会发生变化的请求参数
        - 通常情况下会被隐藏在前台页面
    5.代理中的匿名度都有哪些?分别表示什么意思
    
    6.什么是代理的类型?不同类型代理的区别是什么?
        - http
        - https
    7.简述线程池中map方法的使用方式和其作用
        func_return = map(func,list)
    
    
    单线程+多任务异步协程   v3.6
    - 意义:提升爬取数据的效率
    - 实现异步爬虫的方式
        - 多线程/多进程(不建议)
        - 池(适当)
        - 单线程+多任务异步协程(推荐)
    - 概念
        - 协程:协程对象。可以使用async关键字修饰一个函数的定义(特殊的函数),当该特殊的函数被调用后,就可以返回一个协程对象。
                        当函数调用后,函数内部的实现语句不会被立即执行。
            - 协程 == 特殊函数
        - 任务对象:
            - 本质上就是对协程对象进一步封装。
                - 任务对象 == 特殊函数
            - 给任务对象绑定一个回调
                - add_done_callback(callback)
    
        - 事件循环(EventLoop):无限的循环对象
            - 我们必须将任务对象注册到事件循环对象中,然后开启事件循环对象。
            - 事件循环对象在执行任务对象的时候是基于异步
    
        - await async
    
        - 注意事项:
            - 保证特殊函数内部不可以出现不支持异步模块对应的代码
            - 在特殊函数内部遇到阻塞操作必须使用await关键字对其进行手动挂起
            - 如果想要将多个任务对象注册到事件循环中,必须将多个任务对象封装到一个列表中,然后将列表注册(必须使用wait方法将列表中的任务对象进行挂起)到事件循环中
    
    
    - aiohttp模块:是一个支持异步的网络请求模块
        - pip install aiohttp
    
    
    
    selenium模块的使用
    - 概念:就是一个基于浏览器自动化的模块。
    - selenium和爬虫之间的关联
        - 很便捷的捕获动态加载的数据 - 可见即可得
        - 实现模拟登陆
    - 使用
        - 环境的安装:
            - pip install selenium
            - 下载一个浏览器的驱动程序
                - 谷歌驱动下载:http://chromedriver.storage.googleapis.com/index.html
                - 驱动程序和浏览器版本的映射关系:http://blog.csdn.net/huilan_same/article/details/51896672
        - 创建某一款一个浏览器对象
    
    - 动作链
        - 如果想要触发一系列连续的行为动作
  • 相关阅读:
    Ubuntu修改root默认密码
    2012年总结
    阿朵,网上传得沸沸扬扬,我们还是听听她的歌吧!
    人力资源开发网站
    关于ant
    ObjectSpaces
    firefox plugs
    xpi插件的安装
    年关
    https的资源
  • 原文地址:https://www.cnblogs.com/XLHIT/p/11310935.html
Copyright © 2011-2022 走看看