使用slenium+chromedriver实现无敌爬虫

    摘要

    @概述 通常各大网站的后台都会有一定的反爬机制,既为了数据安全,也为了减小服务器压力 通常反爬的手段的方向,都 […]

    @概述

    • 通常各大网站的后台都会有一定的反爬机制,既为了数据安全,也为了减小服务器压力
    • 通常反爬的手段的方向,都是识别非浏览器客户端,而selenium所做的事情,恰恰是驱动真正的浏览器去执行请求和操作,只不过信号不是来源于鼠标,而是来源于selenium的API(selenium本是一个自动化的测试工具)
    • 自然人用户能做的一切,selenium几乎都驱动浏览器取做,无论是否有界面,包括输入、点击、滑动,等等
    • 然而到底是鼠标操作的浏览器发起的请求还是API,对于服务端来说,是没有任何差别的
    • 所以说:做人难,做男人难,做一个后台开发的男人难上加难,让我们开始对其实施蹂躏吧

    @一些掌故

    • 早些的时候流行的组合并不是selenium+chrome浏览器驱动,而是selenium+phantomjs
    • phantomjs是一款没有界面的浏览器,业界称作无头浏览器(headless),由于没有界面和渲染,其运行速度要大大优于有界面的浏览器,这恰恰是爬虫喜欢的,因此红极一时
    • 后来chrome和火狐推出了无头模式,且运行速度很流畅,phantomjs已然寿终正寝,因此我们表过不提

      @开发环境的搭建(基于ubuntu)

    • 安装selenium:sudo pip install selenium
    • 如果没有则安装chrome浏览器(尽量更新到58以上):http://www.linuxidc.com/Linux/2016-05/131096.htm
    • 安装chrome浏览器驱动(注意最新版本尾号是29而非9):https://www.cnblogs.com/Lin-Yi/p/7658001.html

    @导包

    您需要选择一个短代码# 导入selenium的浏览器驱动接口
    from selenium import webdriver
    
    # 要想调用键盘按键操作需要引入keys包
    from selenium.webdriver.common.keys import Keys
    
    # 导入chrome选项
    from selenium.webdriver.chrome.options import Options

    @第一个程序:抓取页面内容,生成页面快照

    # 创建chrome浏览器驱动,无头模式(超爽)
    chrome_options = Options()
    chrome_options.add_argument('--headless')
    driver = webdriver.Chrome(chrome_options=chrome_options)
    
    # 加载百度页面
    driver.get("http://www.baidu.com/")
    # time.sleep(3)
    
    # 获取页面名为wrapper的id标签的文本内容
    data = driver.find_element_by_id("wrapper").text
    print(data)
    
    # 打印页面标题 "百度一下,你就知道"
    print(driver.title)
    
    # 生成当前页面快照并保存
    driver.save_screenshot("baidu.png")
    
    # 关闭浏览器
    driver.quit()

    @模拟用户输入和点击搜索,跟真人操作一样!

        # get方法会一直等到页面被完全加载,然后才会继续程序,通常测试会在这里选择 time.sleep(2)
        driver.get("http://www.baidu.com/")
    
        # id="kw"是百度搜索输入框,输入字符串"程序猿"
        driver.find_element_by_id("kw").send_keys(u"程序猿")
    
        # id="su"是百度搜索按钮,click() 是模拟点击
        driver.find_element_by_id("su").click()
        time.sleep(3)
    
        # 获取新的页面快照
        driver.save_screenshot("程序猿.png")
    
        # 打印网页渲染后的源代码
        print(driver.page_source)
    
        # 获取当前页面Cookie
        print(driver.get_cookies())
    
        # ctrl+a 全选输入框内容
        driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'a')
    
        # ctrl+x 剪切输入框内容
        driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'x')
    
        # 输入框重新输入内容
        driver.find_element_by_id("kw").send_keys("美女")
    
        # 模拟Enter回车键
        driver.find_element_by_id("su").send_keys(Keys.RETURN)
        time.sleep(3)
    
        # 清除输入框内容
        driver.find_element_by_id("kw").clear()
    
        # 生成新的页面快照
        driver.save_screenshot("美女.png")
    
        # 获取当前url
        print(driver.current_url)
    
        # 关闭浏览器
        driver.quit()

    @模拟用户登录

        # 加载微博登录页
        driver.get("http://passport.weibo.cn/signin/login?entry=mweibo&r=http%3A%2F%2Fweibo.cn%2F&backTitle=%CE%A2%B2%A9&vt=")
        time.sleep(3)
    
        # 找到输入框,键入用户名和密码
        driver.find_element_by_id('loginName').send_keys("worio.hainan@163.com")
        driver.find_element_by_id('loginPassword').send_keys("Qq94313805")
    
        # 点击登录按钮
        driver.find_element_by_id('loginAction').click()
        time.sleep(3)
    
        # 快照显示已经成功登录
        print(driver.save_screenshot('jietu.png'))
        driver.quit()

    @使用cookies登录

        # 加载知乎主页,查看快照知此时处于未登录状态
        driver.get("https://www.zhihu.com")
        time.sleep(1)
        print(driver.save_screenshot("zhihu_nocookies.png"))
    
        # 操作浏览器登录知乎并抓包cookies
        zhihu_cookies = {
            # 'aliyungf_tc' : 'AQAAAAR4YFOeswAAnLFJcVRd4MKOTTXu',
            'l_n_c': '1',
            'q_c1': '8572377703ba49138d30d4b9beb30aed|1514626811000|1514626811000',
            'r_cap_id': 'MTc5M2Y0ODUzMjc0NDMzNmFkNTAzZDBjZTQ4N2EyMTc=|1514626811|a97b2ab0453d6f77c6cdefe903fd649ee8531807',
            'cap_id': 'YjQyZTEwOWM4ODlkNGE1MzkwZTk3NmI5ZGU0ZTY2YzM=|1514626811|d423a17b8d165c8d1b570d64bc98c185d5264b9a',
            'l_cap_id': 'MGE0NjFjM2QxMzZiNGE1ZWFjNjhhZmVkZWQwYzBkZjY=|1514626811|a1eb9f2b9910285350ba979681ca804bd47f12ca',
            'n_c': '1',
            'd_c0': 'AKChpGzG6QyPThyDpmyPhXaV-B9_IYyFspc=|1514626811',
            '_xsrf': 'ed7cbc18-03dd-47e9-9885-bbc1c634d10f',
            'capsion_ticket': '2|1:0|10:1514626813|14:capsion_ticket|44:NWY5Y2M0ZGJiZjFlNDdmMzlkYWE0YmNjNjA4MTRhMzY=|6cf7562d6b36288e86afaea5339b31f1dab2921d869ee45fa06d155ea3504fe1',
            '_zap': '3290e12b-64dc-4dae-a910-a32cc6e26590',
            'z_c0': '2|1:0|10:1514626827|4:z_c0|92:Mi4xYm4wY0FRQUFBQUFBb0tHa2JNYnBEQ1lBQUFCZ0FsVk5DNjAwV3dCb2xMbEhxc1FTcEJPenpPLWlqSS1qNm5KVEFR|d89c27ab659ba979a977e612803c2c886ab802adadcf70bcb95dc1951bdfaea5',
            '__utma': '51854390.2087017282.1514626889.1514626889.1514626889.1',
            '__utmb': '51854390.0.10.1514626889',
            '__utmc': '51854390',
            '__utmz': '51854390.1514626889.1.1.utmcsr=zhihu.com|utmccn=(referral)|utmcmd=referral|utmcct=/',
            '__utmv': "51854390.100--|2=registration_date=20150408=1'3=entry_date=20150408=1",
        }
    
        # 将用户登录产生的cookies全部添加到当前会话
        for k, v in zhihu_cookies.items():
            driver.add_cookie({'domain': '.zhihu.com', 'name': k, 'value': v})
    
        # 再次访问知乎主页并拍照,此时已经是登录状态了
        driver.get("https://www.zhihu.com")
        time.sleep(3)
        print(driver.save_screenshot("zhihu_cookies.png"))
    
        # 退出浏览器
        driver.quit()

    @模拟滚动条的滚动(这个用常规的爬虫很难实现)

        # 加载知乎主页
        driver.get("https://www.zhihu.com")
        time.sleep(1)
    
        # 加载本地cookies实现登录
        for k, v in zhihu_cookies.items():
            driver.add_cookie({'domain': '.zhihu.com', 'name': k, 'value': v})
    
        # 以登录状态再次发起访问
        driver.get("https://www.zhihu.com")
        time.sleep(3)
    
        # 将页面滚动到最后,执行多次
        for i in range(3):
            js = "var q=document.documentElement.scrollTop=10000"
            driver.execute_script(js)
            time.sleep(3)
    
        # 截图并退出,页面侧边滚动条已经下滑了许多像素
        print(driver.save_screenshot("zhihu_scroll.png"))
        driver.quit()

    @一边滚动一边加载

    • 唯品会首页的女装图片,是一边滚动一边进行ajax异步加载的
    • 这个靠常规的抓包实现起来很麻烦
    • 使用selenium我们只需模拟用户多次下拉滚动条,一段时间之后再重新拿取渲染好的页面源码,就可以像爬取静态页面那样去爬取图片了
    • 类似这种操作,其实质就是开挂,是几乎无法防守的
        # 唯品会女装图片链接无法直接获得
        # 请求唯品会页面
        driver.get("https://category.vip.com/search-3-0-1.html?q=3|30036||&rp=30074|30063&ff=women|0|2|2&adidx=1&f=ad&adp=65001&adid=326630")
        time.sleep(3)
    
        # 逐渐滚动浏览器窗口,令ajax逐渐加载
        for i in range(1, 10):
            js = "var q=document.body.scrollTop=" + str(500 * i)  # PhantomJS
            js = "var q=document.documentElement.scrollTop=" + str(500 * i)  # 谷歌 和 火狐
    
            driver.execute_script(js)
            print('=====================================')
            time.sleep(3)
    
        # 拿到页面源码
        html = etree.HTML(driver.page_source)
        all_img_list = []
    
        # 得到所有图片
        img_group_list = html.xpath("//img[contains(@id,'J_pic')]")
        # img_group_list = html.xpath("//img[starts-with(@id,'J_pic')]")
        # 正则表达式匹配
        # img_group_list = html.xpath(r'//img[re:match(@id, "J_pic*")]',namespaces={"re": "http://exslt.org/regular-expressions"})
    
        # 收集所有图片链接到列表
        for img_group in img_group_list:
            img_of_group = img_group.xpath(".//@data-original | .//@data-img-back | .//@data-img-side")
            print(img_of_group)
            all_img_list.append('\n'.join(img_of_group) + '\n')
    
        # 将收集到的数据写入文件
        with open('vip.txt', 'w', encoding='utf-8') as f:
            f.write('\n'.join(all_img_list))
    
        # 退出浏览器
        driver.quit()

    继续阅读
    avatar
    Python告诉你iPhone X有多热卖 技术•随笔

    Python告诉你iPhone X有多热卖

    老婆最近生气了,说强哥不肯给她买iPhone X。强哥觉得挺委屈的,强哥是小气的人么。老婆要买iPhone X,强哥当然支持了。强哥立刻转了一笔巨款给老婆 发完转账,老婆就把强哥给拉黑了。强哥当时的心...
    匿名

    发表评论

    匿名网友 填写信息

    :?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

    确定