Python3.x:Selenium+PhantomJS爬取帶Ajax、Js的網頁


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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM