从零开始写Python爬虫 --- 3.1 Selenium模拟浏览器

从零开始写Python爬虫 --- 3.1 Selenium模拟浏览器

本来说好要写Mechanize模拟浏览器的,结果一看居然只支持2.x版本的Python,而且已经长久没有更新维护了,本着学新不学旧的原则,我决定跳过他,直接开学Selenium(其实就是我懒,逃


Selenium的介绍:

为什么我们要使用这个包呢?在写Python爬虫的时候,最麻烦的不是那些海量的静态网站,而是那些通过JavaScript获取数据的站点。Python本身对js的支持就不好,所以就有良心的开发者来做贡献了,这就是Selenium,他本身可以模拟真实的浏览器,浏览器所具有的功能他一个都不拉下,加载js更是小菜了。


Selenium的安装:

安装起来依旧很简单,我们用pip工具安装:

pip install selenium

现在Selenium的最新版本是3.4.2

找到一分还不错的中文文档:
Selenium with Python中文翻译文档


浏览器的选择:

在写爬虫的时候,用到最多的就是Selenium的Webdriver,

当然,webdriver也不可能支持所有的浏览器,让我们看看他支持哪些浏览器吧:

ipython
from selenium import webdriver
help(webdriver)

# OUT:

PACKAGE CONTENTS
    android (package)
    blackberry (package)
    chrome (package)
    common (package)
    edge (package)
    firefox (package)
    ie (package)
    opera (package)
    phantomjs (package)
    remote (package)
    safari (package)
    support (package)

可以看到,Selenium支持的浏览器还是非常丰富的,
无论是移动端的Android、blackberry
还是我们电脑常用的Chrome,Safari,Firefox。
然而,在写爬虫的 时候,我推荐使用PhantomJS:

PhantomJS是一个而基于webkit的服务器端的JS API。

他全面支持各种原生的Web标准:DOM处理、CSS选择器、JSON、Canvas和SVG。最重要的是他是一个没有GUI的程序,

也就意味着他可以省去大量的加载图形界面的时间。

有人曾经测试过,使用Selenium模块调用上述浏览器,PhantomJS的速度是第一名哦~

第二和第三是chrome和ie。



PhantomJS的安装:

这里有一点要说明,PhantomJS并不是一个Python模块,他是一个独立的,第三方软件,这也就意味着我们不能简单的使用pip工具安装啦。


  • Mac下安装PhantomJS:
  • 这里我们只要使用brew工具就能安装上PhantomJs了

    brew install phantomjs

    如果你的mac还没有安装过Brew,只需要下面行命令就能成功安装了:

    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

    • linux下安装PhantomJS:


    linux下有很多第三方发型版本:
    比较常用的一般是 Ubuntu、centos等等
    这些发行版也都有自己强大的软件管理仓库:apt、yum等等

    那么安装起来也就超方便了:

    # ubuntu
    apt-get install phantomjs
    
    # centos
    yum install phantomjs
    • win下安装PhantomJS:


    虽然win下没有上述的方便的安装方式,
    但是我们可以去官网下载安装包,然后在安装
    地址在这:Download | PhantomJS



    使用Selenium&PhantomJS抓取数据:

    本着第一个例子一定要简单明了,我们拿百度开刀:

    打开百度首页:

    我们用ipython来进行试验:

    ipython
    
    In [1]: from selenium import webdriver
    
    In [2]: browser = webdriver.PhantomJS()
    
    In [3]: url = 'https://www.baidu.com'
    
    In [4]: browser.get(url)
    
    In [5]: browser.implicitly_wait(3)
    
    

    我们首先导入了Selenium里的webdriver,
    然后建立一个PhantomJS的浏览器对象,
    最后我们通过get方法,打开了百度的首页。
    这里要说一下 implicitly_wait():

    浏览器解释JS脚本是需要时间的,但实际上这个时间并不好确定,
    如果我们手动设定时间间隔的话,设置多了浪费时间,设置少了又会丢失数据

    implictly_wait函数则完美解决了这个问题,给他一个时间参数,他会只能等待,当js完全解释完毕就会自动执行下一步。


    找到搜索框和搜索按钮:

    在第一步的时候,我们其实就已经把百度首页的数据爬到本地了,

    剩下当然是数据的筛选,这里推荐用Selenium的自带函数来完成,
    Selenium 本事给出了18个函数来定位有效数据的位置:

    # 找到第一个匹配的元素
    find_element_by_id
    find_element_by_name
    find_element_by_xpath
    find_element_by_link_text
    find_element_by_partial_link_text
    find_element_by_tag_name
    find_element_by_class_name
    find_element_by_css_selector
    
    # 一次查找多个元素 (这些方法会返回一个list列表):
    find_elements_by_name
    find_elements_by_xpath
    find_elements_by_link_text
    find_elements_by_partial_link_text
    find_elements_by_tag_name
    find_elements_by_class_name
    find_elements_by_css_selector
    

    相信在用过bs4和Xpath之后,用这个完全没有什么压力吧,
    看函数名就应该知道是具体通过什么来定位数据了

    上面我们只是打开了百度而已,
    我们在使用真实浏览器的时候
    是不是要现在文本框里输入关键词
    然后在按搜索按钮呢?

    在PhantomJS里我们也需要这样做:

    In [6]: text = browser.find_element_by_id('kw')
    
    In [7]: text.clear()
    
    In [8]: text.send_keys('python')
    
    In [9]: browser.title
    Out[9]: 'python_百度搜索'
    
    In [10]: button = browser.find_element_by_id('su')
    
    In [11]: button.submit()
    

    用chrome开发者工具可以快速定位到各个element的位置:


    我们首先调用find_element_by_id()方法找到了text栏的位置,
    然后通过send_keys()方法来输入关键字
    接着还是通过find_element_by_id()方法找到提按钮,
    最后我们通过.submint()方法来模拟点击,发送搜索请求

    让我们来筛选答案吧:

    In [13]: results = browser.find_elements_by_class_name('t')
    
    In [14]: for result in results:
        ...:     print('标题:{} 超链接:{}'.format(result.text,
        ...:                                 result.find_element_by_tag_name('a').ge
        ...: t_attribute('href')))
    
    # 结果节选:
    标题:Welcome to Python.org官网 超链接:http://www.baidu.com/link?url=AfMsWMp47YyrqHsvNqAUV_I79v7x7_V50FRhffEqyzC
    标题:Python_百度百科 超链接:http://www.baidu.com/link?url=O_mv6kHvjl4aHJnIy5RslTb4HGxiqCQ5Aa8jxvL738E66QIh6YutyPaTLzSkgF_oR6csfMZl3fBcvk899HTvOq
    标题:Download Python | Python.org 超链接:http://www.baidu.com/link?url=MiTrsrkdbR9MsqAKqPQB0gg_qq1vNjitwo6JXs-epElh1PRopw0iwylA2J7zOPK1
    标题:Python 基础教程 | 菜鸟教程 超链接:http://www.baidu.com/link?url=87DkBMsuYKPIErgWyHQ8gYARtiajq2Be7CuCkwaVGAUYJ6S9-PenmAKVzZ4p4LL5dev4h1-BX1xNiRQmGueNv_
    标题:Mac版 Python最新官方版下载_百度软件中心 超链接:http://www.baidu.com/link?url=NXz2Ztu2_uEIr98kwl5mDdxeyIfiuZYVqb82llW_azuGiSudgeZinDvvUgtUMhCEbOdzHqBpTE-nnMZSH3FT2q
    标题:玩蛇网 - Python教程学习与Python资源分享平台 超链接:http://www.baidu.com/link?url=owZ9vkSBVqs3isRCbwIFtOqzT44ChUW8WaNwC0ZJtcxa4YcRAD3ioTduKOgGyyJb
    标题:python吧_百度贴吧 超链接:http://www.baidu.com/link?url=1xbKTtfvuOddE83Pj9AnKOywjwlwlvTQTyqtNSKwJZ19QPgyMQye3HgwPsaneR5221CzJ07I0MGS2pcGFX8rCq
    标题:Python 简介 | 菜鸟教程 超链接:http://www.baidu.com/link?url=mNZA6drSbW4EJIMd5-qNRnqk6C5wvZozyE-nmJfy2EOPDPe5p75orkw5oKQ4USkjSTCt6bCRhaKlHgWHIMtBlK
    标题:Python教程 - 廖雪峰的官方网站 超链接:http://www.baidu.com/link?url=qmDG-Rbus9jnQZvvWvS3gjVnqUPTFlEbIWWvPisvfrSEEf7r4pieLJVT6S3XslKBZgXzmezFEYH3tv9AIKDyycbcbZeITZNIb5RR6Xn6qAE3Sgibs4mMmre6PXqXMNDB
    

    这次我们通过browser.find_elements_by_class_name()方法定位到搜索结果,
    返回一个element类型的列表,
    再通过element.text 和 element.get_attribute()方法来获取我们需要的数据。
    最后我们遍历一边results列表就能获得我们想要的答案了。


    来看一下完整的代码:

    '''
    使用Selenium模拟浏览器
    抓取百度查询结果
    '''
    
    # 导入selenium模块中的web引擎
    from selenium import webdriver
    
    
    # 建立浏览器对象 ,通过Phantomjs
    browser = webdriver.PhantomJS()
    
    # 设置访问的url
    url = 'https://www.baidu.com'
    
    # 访问url
    browser.get(url)
    
    # 等待一定时间,让js脚本加载完毕
    browser.implicitly_wait(3)
    
    # 找到搜索框
    text = browser.find_element_by_id('kw')
    
    # 清空搜索框的文字
    text.clear()
    
    # 填写搜索框的文字
    text.send_keys('python')
    
    # 找到submit按钮
    button = browser.find_element_by_id('su')
    
    # 点击按钮 提交搜索请求
    button.submit()
    
    
    # 查看当前浏览器标题
    print(browser.title)
    
    # 以截图的方式查看浏览器的页面
    browser.save_screenshot('text.png')
    
    # 找到结果 结果保存为列表变量
    results = browser.find_elements_by_class_name('t')
    
    # 循环遍历找出每个结果的标题和url
    for result in results:
        print('标题:{} 超链接:{}'.format(result.text,
                                    result.find_element_by_tag_name('a').get_attribute('href')))
    

    这里只是简单介绍了如何通过Selenium和PhantomJS来模拟浏览器抓取数据,后面会再来几个实战的例子。



    每天的学习记录都会 同步更新到:
    微信公众号: findyourownway

    知乎专栏:从零开始写Python爬虫 - 知乎专栏

    blog : www.ehcoblog.ml

    Github: Ehco1996/Python-crawler

    编辑于 2017-05-26

    文章被以下专栏收录