Python3.x:Selenium+PhantomJS爬取带Ajax、Js的网页

前言 

  现在很多网站的都大量使用JavaScript,或者使用了Ajax技术。这样在网页加载完成后,url虽然不改变但是网页的DOM元素内容却可以动态的变化。如果处理这种网页是还用requests库或者python自带的urllib库那么得到的网页内容和网页在浏览器中显示的内容是不一致的。

解决方案

  使用Selenium+PhantomJS。这两个组合在一起,可以运行非常强大的爬虫,可以处理cookie,JavaScript,header以及其他你想做的任何事情。 

安装第三方库

  Selenium是一个强大的网络数据采集工具,最初是为网站自动化测试开发的,其有对应的Python库;

  Selenium安装命令:

pip install selenium

安装PhantomJS

  PhantomJS是一个基于webkit内核的无头浏览器,即没有UI界面,即它就是一个浏览器,只是其内的点击、翻页等人为相关操作需要程序设计实现。通过编写js程序可以直接与webkit内核交互,在此之上可以结合java语言等,通过java调用js等相关操作。需要去官网下载对应平台的压缩文件;

PhantomJS(phantomjs-2.1.1-windows)下载地址:http://phantomjs.org/download.html

下载PhantomJs 然后将 解压后的执行文件放在被设置过环境变量的地方,不设置的话,后续代码就要设, 所以这里直接放进来方便;

然后检测下,在cmd窗口输入phantomjs:

出现这样的画面,即表示成功;

示例一:

  Selenium+PhantomJS示例代码:

from selenium import webdriver 
 
driver = webdriver.PhantomJS() 
driver.get('http://www.cnblogs.com/lizm166/p/8360388.html') 
#获取网页源码 
data = driver.page_source 
print(data) 
#获取元素的html源码 
tableData = driver.find_element_by_tag_name('tableData').get_attribute('innerHTML') 
#获取元素的id值 
tableI = driver.find_element_by_tag_name('tableData').get_attribute('id') 
#获取元素的文本内容 
tableI = driver.find_element_by_tag_name('tableData').text 
#循环测试 
list_container = driver.find_elements_by_xpath("//div[@class='list-container mb-bg']/dl/dt/h3/a")  
for title in list_container:   
    print 'Num' + str(SUMRESOURCES +1)   
    print u'标题: ' + title.text   
    print u'链接: ' + title.get_attribute('href') 
 
driver.quit()    

  能输出网页源码,说明安装成功

示例二:

  通过这两者来解决客户端重定向问题的例子:

  程序首先加载了driver对象,然后请求网站,之后没0.5秒检测网站的html元素,如果html元素发生改变则认为页面发生了重定向,然后打印重定向后的页面内容。

  代码:

from selenium import webdriver 
import time 
from selenium.webdriver.remote.webelement import WebElement 
from selenium.common.exceptions import StaleElementReferenceException 
 
 
# 处理重定向,可以定时检查页面的某元素 
# 如果和先前的不一致则可认为客户端重定向 
def wait_for_load(driver): 
    #elem = driver.find_element_by_tag_name("html") 
    title = driver.find_element_by_tag_name("title") 
    #print(title) 
    count = 0 
    while True: 
        count += 1 
        if count > 20: 
            print("Timing out after 10 seconds and returning") 
            return 
        time.sleep(.5) 
 
        newtitle = driver.find_element_by_tag_name("title") 
        if newtitle != title: 
            return 
        #try: 
        #    elem = driver.find_element_by_tag_name("html") 
        #except StaleElementReferenceException: 
        #    return 
 
driver = webdriver.PhantomJS(executable_path='./phantomjs') 
driver.get("http://pythonscraping.com/pages/javascript/redirectDemo1.html") 
wait_for_load(driver) 
print(driver.page_source)

 示例三:

import requests 
from bs4 import BeautifulSoup 
from selenium import webdriver 
 
def getData(dataUrl): 
    #获取ajax返回的页面(用bs4获取不到ajax返回的数据) 
    driver = webdriver.PhantomJS() 
    driver.get(dataUrl) 
    #获取table元素 
    tables = driver.find_elements_by_tag_name('table') 
    if tables is None: 
        print('网页加载获取数据失败') 
        logger.info('网页加载获取数据失败') 
    #获取table元素中的tr元素 
    trList = tables[0].find_elements_by_tag_name('tr') 
    if trList is None: 
        print('网页加载获取数据失败') 
        logger.info('网页加载获取数据失败') 
    for i in range(0,len(trList)): 
        if i > 0: 
            #获取table元素中的tr元素中的td元素 
            tdList = trList[i].find_elements_by_tag_name('td') 
            if tdList is not None: 
                for n in range(0,len(tdList)): 
                    #获取td元素文本内容 
                    print(">>>>%s:%s"%(n,tdList[n].text)) 
    driver.quit() 
 
def getDataUrl(issueid): 
    dataUrl = '' 
    url = "http://******/Scsj_tjyb_issue.jsp" 
    headerDict = {'Host': '******', 
                  'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.31 Safari/537.36', 
                  'Accept': '*/*', 
                  'Accept-Language': 'zh-CN,zh;q=0.8', 
                  'Accept-Encoding': 'gzip, deflate', 
                  'Origin':'http://******, 
                  'Referer': 'http://******/tjyb_front/', 
                  'Connection': 'keep-alive'} 
    data = {'AJAX': '1', 'TEMPLATE_ID': '1114', 
            'ISSUEID': issueid, 'CATALOGTYPE': 'main', 
            'LANGUAGE': 'zh', 'HEAD': ''} 
    res = requests.post(url, data=data, headers=headerDict) 
    # 获取跳转后的页面源码,返回json串 
    soup = BeautifulSoup(res.content, "html.parser") 
    if soup.find_all('a',target='_blank') is not None: 
        for a_url in soup.find_all('a',target='_blank'): 
            if a_url.string == '******统计表': 
                dataUrl=a_url['href'] 
                break 
    else: 
        print("未获取到a标签") 
        logger.info("未获取到a标签") 
    print('http://******'+dataUrl) 
    return 'http://******'+dataUrl 
 
if __name__ == '__main__': 
    url = getDataUrl('897') 
    getData(url)

 示例四:

#自定义请求头head 
from selenium import webdriver 
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities 
 
#设置自定义请求头参数 
def get_headers_driver(): 
    desire = DesiredCapabilities.PHANTOMJS.copy() 
    headers = {'Accept': '*/*', 
               'Accept-Language': 'en-US,en;q=0.8', 
               'Cache-Control': 'max-age=0', 
               'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36', 
               'Connection': 'keep-alive', 
               'Referer': 'http://www.baidu.com/' 
               } 
    for key, value in headers.items(): 
        desire['phantomjs.page.customHeaders.{}'.format(key)] = value 
    driver = webdriver.PhantomJS(desired_capabilities=desire, service_args=['--load-images=yes'])#将yes改成no可以让浏览器不加载图片 
    return driver 
 
# 登录 
def login(): 
    driver = get_headers_driver(cookie) 
    url = "http://******/login/main.do" 
    driver.get(url) 
    #获取网页源码 
    print(driver.page_source)

 注:模拟回车键代码

# 模拟回车 
from selenium.webdriver.common.keys import Keys 
driver.find_element_by_xpath("**").send_keys(Keys.ENTER)

 

发布评论

分享到:

IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

Python3.x:将数据下载到xls时候用xml格式保存一份读取内容详解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。