zoukankan      html  css  js  c++  java
  • 动态渲染反爬虫

    动态渲染反爬虫

    动态网页比静态网页更具有交互性,能给用户提供更好的体验

    动态网页中常见的表现形式有 下拉刷新,点击切换和悬停显示等

    由 JavaScript 改变 HTML DOM 导致页面内容发生变化的现象称为动态渲染



    动态渲染的通用解决办法

    如果每次遇到很麻烦的动态渲染页面,都需要猜接口参数,跟进和分析 JavaScript 代码逻辑

    那么耗费的时间成本就很高了

    当目标网站发生产品迭代升级或针对爬虫有意改动代码,爬虫工程师就需要做对应的调整

    可能目标网站的前端工程师只花费了 2 小时编写用于加密请求参数的代码,而爬虫工程师却需要花费 3 天甚至更多时间才能分析出正确的计算逻辑

    那么我们就可以用渲染工具,来模拟用户的一些操作,比如点击,滑动和拖拽

    其中常用的是 Puppeteer,Splash,和 Selenium这三种工具


    Selenium套件

    基本使用

    from selenium import webdriver
    
    url = 'http://www.porters.vip/verify/sign'
    
    # 初始化浏览器对象
    brower = webdriver.Chrome()
    # 向指定网址发起 GET 请求
    brower.get(url)
    # 使用 CSS 选择器定位按钮,并点击按钮
    brower.find_element_by_css_selector('#fetch_button').click()
    # 使用 CSS 选择器定位文本,并取出文本内容
    resp = brower.find_element_by_css_selector('#content').text
    
    # 将按钮点击后的网页文本赋值给变量 resp
    # resp = brower.page_source
    print(resp)
    # 程序退出,并关闭浏览器
    brower.quit()
    

    异步渲染库 Puppeteer

    在 Selenium 套件的支持下,我们很轻松的完成了爬取任务

    单 Selenium 套件也有一定的缺陷,当我们使用 Python 中的异步库编写爬虫时,Selenium 就不是那么合适了

    异步是目前提升爬虫效率的常用手段之一,越来越多的人讲同步的爬虫代码改写为异步。由于浏览器是以进程方式启动的,所以它无法满足异步爬虫的渲染需求,为什么这么说呢?

    异步爬虫可以做到每秒向 300 个页面发起请求,单是要在计算机中开启 300 个浏览器进程或者 300 个标签是很困难的,这会导致阻塞,影响异步爬虫程序的整体效率

    如果添加一些加载资源较多的网站或者响应速度很慢的网站,会发现卡顿阻塞所有的请求,这就是同步的缺点,如果用的是多个浏览器对象,即每次请求都初始化一个浏览器对象,虽然可以解决这个问题,但过多的浏览器进程对于系统资源的消耗是非常大的,显然这是一种得不偿失的做法

    这时候我们需要一个能够做到与 Selenium 套件相同的总做并且支持异步的渲染工具

    Puppetetr 正好可以满足我们的需求,Puppeteer 是 Google 开源的 Node 库,它提供了有个高级 API 开控制 Chrome 浏览器,浏览器中大多数手动执行的操作都可以使用 Puppeteer 完成,更重要的是 Puppeteer 支持异步

    Puppeteer 是一个 Node 库,如果你的爬虫程序使用 Node.js 编写的,那么可以直接使用这个库,如果爬虫程序是用 Python 写的,那么久需要用支持 Python 的库 Pypeteer


    示例:

    import asyncio
    from pyppeteer import launch
    
    async def main():
        # 初始化浏览器对象
        browser = await launch()
        # 在浏览器上下文中创建新页面
        page = await browser.newPage()
        # 打开目标网址
        await page.goto('http://www.porters.vip/verify/sign')
        # 点击指定按钮
        await page.click('#fetch_button')
        # 读取页面指定位置的文本
        resp = await page.xpath('//*[@id="content"]')
        text = await (await resp[0].getProperty('textContent')).jsonValue()
        print(text)
        # 关闭浏览器对象
        await browser.close()
    
    asyncio.get_event_loop().run_until_complete(main())
    
  • 相关阅读:
    SharePoint中获取当前登录的用户名
    SharePoint 2013 图文开发系列之InfoPath入门
    在InfoPath中如何获取当前用户的信息(Profile)
    更新当前列并添加其他列
    poj3067 Japan
    poj2481 Cows
    poj1195 Mobile phones
    poj2299 Ultra-QuickSort
    lower_bound()和upper_bound
    hdu4339 Query
  • 原文地址:https://www.cnblogs.com/kai-/p/12252981.html
Copyright © 2011-2022 走看看