selenium模拟浏览器&PhantomJS

发布时间:2018-07-24 16:21:50编辑:Run阅读(7572)

    注意:最新版本的selenium停止对PhantomJS的支持(可以使用谷歌&火狐的无头浏览器),如果还想用PhantomJS,需要对selenium降级

    卸载最新版本:pip3 uninstall selenium

    安装老版本:pip3 install selenium==3.8.0


    Python网络爬虫中最麻烦的不是那些需要登录才能获取数据的网站,而是那些通过JavaScript获取数据的网站。python对javascript的支持不太好,所以就需要模拟浏览器。这个模拟浏览器跟Mechanize模块稍有不同,Mechanize模块并不支持javascript,所以这里需要一款可以模拟真实浏览器的模块---Selenium模块



    浏览器选择

    在编写Python网络爬虫时,主要用到Selenium的Webdriver, Selenium的Webdriver不可能支持所有的浏览器,也没有必要支持所有浏览器


    webdriver支持列表

    查看模块的功能,最简单也是最方便的方法就是直接使用help命令

    from selenium import webdriver
    help(webdriver)


    运行结果:


    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)

        webkitgtk (package)


    在上面列表中, android和blackberry是移动端的浏览器,移动端和PC端两码事,可以先忽略,剩下的有谷歌,ie,火狐,opera等等,而PhantomJS可能很多人没有听说过


    PhantomJS是一个基于webkit的服务端JavaScriptAPI,它全面支持web而不需浏览器支持,其快速,原生支持各种web标准:DOM处理,CSS选择器,JSON,Canvas和SVG。PhantomJS可以用于页面自动化,网络监测,网页截屏,以及无界面测试等。事实上,在爬JavaScript才能返回数据的网站时,没有比Selenium和PhantomJS更适合的组合了


    windows下安装PhantomJS

    下载地址:http://phantomjs.org/download.html  

    进入下载页面后,选择windows版本的Phantomjs下载,如果是其它系统,对应下载版本安装就好

    blob.png


    下载完成后,解压压缩包,直接将解压后的Phantomjs.exe复制到python的目录中就可以了,如下图

    blob.png


    在python环境中测试一下,如下

    #!/usr/bin/env python
    # coding: utf-8
    
    
    from selenium import webdriver
    driver = webdriver.PhantomJS()



    Selenium  &  PhantomJS抓取数据

    Selenium和PhantomJS配合,可以模拟浏览器获取包括JavaScript的数据,现在不单要获取网站数据,还需要过滤出"有效数据"才行,Selenium本身就带有一套自己的定位过滤函数,它可以很方便地从网站返回的数据中过滤出所需的“有效数据”.


    获取百度搜索结果

    鉴于Selenium.Webdriver的help文件太大,分屏显示又不太方便,干脆将帮助文件保存到文件中慢慢查看,执行命令

    #!/usr/bin/env python
    # coding: utf-8
    
    import sys
    from selenium import webdriver
    
    browser = webdriver.PhantomJS()
    out = sys.stdout
    sys.stdout = open('browserHelp.txt', 'w')
    help(browser)
    sys.stdout.close()
    sys.stdout = out
    browser.quit()

    运行截图

    blob.png



    想获取"有效信息",第一步当然是网站获取返回数据,第二步就是定位"有效数据"的位置,第三步就是从定位中获取“有效数据”.

    以百度搜索为例,使用百度搜索"Python Selenium",并保存第一页搜索结果的标题和链接。从服务器返回数据,由PhantomJS负责,获取返回的数据用Selenium.Webdriver自带的方法page_source,例如:

    from selenium import webdriver
    URL = 'https://www.baidu.com'
    browser = webdriver.PhantomJS()
    browser.get(URL)
    html = browser.page_source
    print(html)

    运行结果:

    blob.png



    第二种方法:直接用selenium&PhantomJS打开百度的主页,然后模拟搜索关键字。直接从Selenium&PhantomJS中返回数据,使用第二种方法,可以很清楚地看到Selenium&PhantomJS获取数据的过程

    执行代码:

    from selenium import webdriver
    browser = webdriver.PhantomJS()
    browser.get('https://www.baidu.com')
    browser.implicitly_wait(10)
    print(browser.page_source)

    执行结果

    blob.png


    PS:关注一个函数implicitly_wait()。使用Selenium&PhantomJS最大的优势是支持JavaScript,而PhantomJS浏览器解释JavaScript是需要时间的,这个时间是多少并不好确定,当然可以用time.sleep()强行休眠等待一个固定时间.但是这个时间定长了,浪费时间;定短了,又没能完整解释JavaScript,而implicitly_wait函数则完美地解决了这个问题,给implicitly_wait一个时间参数,implicitly_wait会智能等待,只要解释完成了就进行下一步,完全没有浪费时间

    下面从网页的框架中选取表单框,并输入搜索的关键词,完成搜索的过程



    获取搜索结果

    Selenium本身给出了18个函数,总共有8种方法从返回数据中定位“有效数据”位置,这些函数分别是:

    find_element(self, by=By.ID, value=None)
    find_element_by_class_name(self, name)
    find_element_by_css_selector(self, css_selector)
    find_element_by_id(self, id_)
    find_element_by_link_text(self, link_text)
    find_element_by_name(self, name)
    find_element_by_partial_link_text(self, link_text)
    find_element_by_tag_name(self, name)
    find_element_by_xpath(self, xpath)
    
    find_elements(self, by=By.ID, value=None)
    find_elements_by_class_name(self, name)
    find_elements_by_css_selector(self, css_selector)
    find_elements_by_id(self, id_)
    find_elements_by_link_text(self, text)
    find_elements_by_name(self, name)
    find_elements_by_partial_link_text(self, link_text)
    find_elements_by_tag_name(self, name)
    find_elements_by_xpath(self, xpath)

    这18个函数前面的9个带element的函数将返回第一个符合参数要求的element,后面9个带elements的函数将返回一个列表,列表中包含所有符合参数要求的element.

    上面函数中,不带by的函数,配合参数可以替代其他的函数.例如:find_element(by='id',value='abc')就可以替代find_element_by_id('abc')。同理find_elements(by='id',value='abc')也可以代替find_elements_by_id('abc').


    这8种定位方法组合应用,灵活配合,可以获取定位数据中的任意位置。

    在使用浏览器请求数据时,用find_element_by_name、find_element_by_class_name、find_element_by_id、find_element_by_tag_name会比较方便。一般的表单,元素都会有name,class,id,这样定位会比较方便。如果仅仅是为了获取“有效数据”的位置,那还是find_element_by_xpath和find_element_by_css比较方便,强烈推荐find_element_by_xpath,真的是超级方便



    先定位文本框,输入搜索关键词并向服务器发送数据,在浏览器中打开百度,定位输入框查看代码,如下图:

    blob.png


    从上图中可以看出文本框里有class,name,id属性,可以使用find_element_by_class_name、find_element_by_id、find_element_by_name来定位。执行命令:

    testElement = browser.find_element_by_class_name('s_ipt')
    testElement = browser.find_element_by_name('wd')
    testElement = browser.find_element_by_id('kw')   # 这三个任选其一都可以定位到
    testElement.clear()
    testElement.send_keys('Python selenium')  # 在输入框中输入关键字


    回到浏览器中,定位submit按钮,如下

    blob.png


    从上图中看出,submit按键有id,class属性,可以用find_element_by_class_name和find_element_by_id来定位,执行命令:

    submitElement = browser.find_element_by_class_name('bg s_btn btnhover')
    submitElement = browser.find_element_by_id('su')  # 这两个任选一个
    submitElement.click()
    print(browser.title)


    代码:

    from selenium import webdriver
    browser = webdriver.PhantomJS()
    browser.get('https://www.baidu.com')
    browser.implicitly_wait(10)
    testElement = browser.find_element_by_class_name('s_ipt')
    testElement.send_keys('Python selenium')
    submitElement = browser.find_element_by_id('su')
    submitElement.click()
    print(browser.title)

    运行结果:

    Python selenium_百度搜索


    此时browser已经获取到了搜索的结果了


    获取有效数据位置

    获取“有效数据”位置或者说是element,先定位搜索结果的标题和链接。在浏览器打开百度搜索Python seleninum,在搜索结果页面中查看源代码

    blob.png



    在这里发现了比较特别的属性class="c-tools"

    blob.png


    发现共有10个结果,可以用find_elements_by_class_name定位所有的搜索结果了,执行命令

    resultElements = browser.find_elements_by_class_name("result c-container ")
    print(len(resultElements))


    从位置中获取有效数据

    有效数据的位置确定后,如何从位置中过滤出有效的数据呢?一般就是获取element的文字或者获取Element中某个属性值。

    Selenium有自己独特的方法:

    import json
    resultElements = browser.find_elements_by_class_name("c-tools")
    print(len(resultElements))
    value = resultElements[0].get_attribute('data-tools')
    valueDic = json.loads(value)
    print(valueDic.get('title'))
    print(valueDic.get('url'))

    执行结果

    10

    Selenium with Python — Selenium Python Bindings 2 ...

    http://www.baidu.com/link?url=CSU8JkNWTcCvLT0miYp8_frqdg7UTLGNjYJyv5cbc71oTDC_ZZNxUIbfu5bZa9Xu

    完整代码如下:

    遍历resultElements列表,可以获取所有的搜索结果的title和url,已将Selenium&PhantomJS爬虫运行了一遍

    from selenium import webdriver
    browser = webdriver.PhantomJS()
    browser.get('https://www.baidu.com')
    browser.implicitly_wait(10)
    testElement = browser.find_element_by_id('kw')
    testElement.send_keys('Python selenium')
    submitElement = browser.find_element_by_id('su')
    submitElement.click()
    
    import json
    resultElements = browser.find_elements_by_class_name("c-tools")
    for i in resultElements:
        value = i.get_attribute('data-tools')
        valueDic = json.loads(value)
        print(valueDic.get('title'))
        print(valueDic.get('url'))

    运行结果:

    blob.png

关键字

上一篇: 没有了

下一篇: Selenium&PhantomJS实战一:获取代理ip