日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动态网页的抓取

發(fā)布時間:2024/2/28 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态网页的抓取 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

已寫章節(jié)

第一章 網(wǎng)絡(luò)爬蟲入門
第二章 基本庫的使用
第三章 解析庫的使用
第四章 數(shù)據(jù)存儲
第五章 動態(tài)網(wǎng)頁的抓取

文章目錄

      • 已寫章節(jié)
  • 第五章 動態(tài)網(wǎng)頁的抓取(Selenium)
    • 5.1 Ajax的原理
    • 5.2 Selenium的使用
      • 5.2.1 準(zhǔn)備工作
      • 5.2.2 Selenium的使用
        • 1. 聲明瀏覽器對象
        • 2. 訪問頁面
        • 3. 查找節(jié)點
        • 4. 查找多個節(jié)點
        • 5. 節(jié)點交互
        • 6. 動作鏈
        • 7. 滑動頁面
        • 8. 執(zhí)行JavaScript
        • 9. 獲取節(jié)點的信息
        • 10. 切換Frame
        • 11. 等待
        • 12. 控制頁面前進(jìn)和后退
        • 13. 對cookies的操作
        • 14. 選項卡
        • 15. 模擬輸入鍵盤
        • 16. 異常處理
    • 5.3 使用Selenium的例子


第五章 動態(tài)網(wǎng)頁的抓取(Selenium)

有時候我們在用requests抓取頁面的時候,得到的結(jié)果可能和我們在瀏覽器中看到的結(jié)果不一樣:在瀏覽器中可以正常看到頁面數(shù)據(jù),但是使用requests得到的結(jié)果并沒有。這是因為requests庫獲取的都是原始的HTML文檔,而在瀏覽器中看到的頁面是經(jīng)過JavaScript處理數(shù)據(jù)后生成的結(jié)果,這些數(shù)據(jù)來源有很多種,可能是通過Ajax加載的,可能是包含在HTML文檔中的,也有可能是經(jīng)過JavaScript和特定的算法計算后生成的。如果是通過Ajax加載的,原始頁面最初不會包含某些數(shù)據(jù),原始頁面加載完之后,會再向服務(wù)器請求某個接口獲取數(shù)據(jù),然后數(shù)據(jù)才被處理從而呈現(xiàn)在網(wǎng)頁上,這其實就是發(fā)生了一個Ajax請求。如果遇到這樣的頁面,需要分析出網(wǎng)頁后臺向服務(wù)器發(fā)送的Ajax請求,如果可以使用requests來模擬Ajax請求,那么就可以成功抓取了。


5.1 Ajax的原理

Ajax(Asynchronous JavaScript nad XML),即異步的JavaScript和XML。它不是一門編程語言,而是利用JavaScript在保證網(wǎng)頁不被刷新、頁面不改變的情況下與服務(wù)器交換數(shù)據(jù)并更新部分網(wǎng)頁的技術(shù)。

例如:打開tx視頻,在電影中,鼠標(biāo)的滑輪向下劃,你會發(fā)現(xiàn)電影好像沒有盡頭,有時候最下面會出現(xiàn)加載的動畫。頁面其實并沒有整個刷新,鏈接也并沒有變化,但是網(wǎng)頁中新增加了電影,這就是通過Ajax獲取新數(shù)據(jù)并呈現(xiàn)的過程。

Ajax有其特殊的請求類型,它是xhr,可以在Chrome的檢查中選擇xhr查看。

模擬Ajax請求來爬取tx視頻的例子:

import requests from fake_useragent import UserAgent from lxml import etree import re from typing import NoReturn, List import time import mysql.connectordef start() -> NoReturn:first_url = 'https://v.qq.com/channel/movie?listpage=1&channel=movie&itype=100062'base_url = 'https://v.qq.com/x/bu/pagesheet/list?append=1&channel=movie&itype=100062&listpage=2&offset={}&pagesize=30'create_table()storage_MysqlDB(get_page(first_url), 1)page_numbers = ((get_number_of_movies(first_url)-30)//30)+1for i in range(1, page_numbers):url = base_url.format(str(i*30))storage_MysqlDB(get_page(url), (i*30)+1)# time.sleep(5)def get_number_of_movies(url: str) -> int:headers = {'user-Agent': UserAgent().chrome}response = requests.get(url=url, headers=headers)response.encoding = response.apparent_encodinge = etree.HTML(response.text, etree.HTMLParser())number_of_movies = e.xpath('//body/div[5]/div/div/div/span/text()')[0]return int(number_of_movies)def get_page(url: str) -> List[List]:response = requests.get(url=url, headers={'user-Agent': UserAgent().chrome})response.encoding = response.apparent_encodinge = etree.HTML(response.text, etree.HTMLParser())all_div = e.xpath('//div[@class="list_item"]')res = []for div in all_div:movies_name = div.xpath('./div[1]/a/@title')hrefs = div.xpath('./div[1]/a/@href')performers = div.xpath('./div[1]/div/text()')performers = [i.replace('主演:', '') for i in performers]number_of_observers = div.xpath('./div[2]/text()')film_length = div.xpath('./a/div[1]/text()')score = div.xpath('./a/div[2]/text()')if len(movies_name) == 0:movies_name = ['None']if len(hrefs) == 0:hrefs = ['None']if len(performers) == 0:performers = ['None']if len(number_of_observers) == 0:number_of_observers = ['None']if len(film_length) == 0:film_length = ['None']if len(score) == 0:score = ['None']tem = []tem.append(str(movies_name[0]))tem.append(str(hrefs[0]))tem.append(str(performers[0]))tem.append(str(number_of_observers[0]))tem.append(str(film_length[0]))tem.append(str(score[0]))res.append(tem)print(res)return resdef create_table():mydb = mysql.connector.connect(host='localhost',user='root',passwd='123456',port=3307,charset='utf8')mycursor = mydb.cursor()sql_create_table = ["USE reptile;","CREATE TABLE IF NOT EXISTS tencent_movies(\ID INT AUTO_INCREMENT COMMENT '編號',\movies_name VARCHAR(40) COMMENT '電影名',\hrefs VARCHAR(100) COMMENT '鏈接',\performers VARCHAR(100) COMMENT '主演',\number_of_observers VARCHAR(20) COMMENT '播放量',\film_length VARCHAR(20) COMMENT '電影時長',\score varchar(4) COMMENT '評分',\PRIMARY KEY(ID)\)COMMENT = 'All movie information in Tencent video'\ENGINE = INNODB CHARSET='utf8mb4' COLLATE='utf8mb4_unicode_ci';"]for i in sql_create_table:mycursor.execute(i)def storage_MysqlDB(data: List, start: int)-> None:mydb = mysql.connector.connect(host='localhost',user='root',passwd='123456',port=3307,charset='utf8',database='reptile')mycursor = mydb.cursor()sql_insert = "insert into tencent_movies values(%s, %s, %s, %s, %s, %s, %s)"for i in data:i.insert(0, start)new_i = tuple(i)mycursor.execute(sql_insert, new_i)# print(start)# time.sleep(1)start += 1mydb.commit()mycursor.close()if __name__ == '__main__':start()

在上面,我們介紹了Ajax,并使用requests來模擬Ajax請求來爬取數(shù)據(jù)。

但是,JavaScript動態(tài)渲染頁面不止Ajax這一種。有很多網(wǎng)頁是由JavaScript產(chǎn)生的,并不會包含Ajax請求。淘寶頁面也是使用Ajax來獲取數(shù)據(jù)的,但是,他的Ajax接口中包含許多的加密參數(shù),我們很難找出其規(guī)律,也很難使用requests來模擬Ajax請求。

為了解決這些問題,我們可以直接使用模擬瀏覽器的方式來實現(xiàn),這樣就可以做到在瀏覽器中看到什么樣子,抓取的源碼就是什么樣子。


5.2 Selenium的使用

Selenium是一個自動化測試工具,利用它可以驅(qū)動瀏覽器執(zhí)行特定的動作,如下拉、點擊按鈕、在文本框中輸入文字、下劃頁面等動作,同時還可以獲取瀏覽器當(dāng)前呈現(xiàn)的頁面的源代碼。可以將Selenium看做是個通過代碼來控制瀏覽器的工具。


5.2.1 準(zhǔn)備工作

  • 需要下載與你的Chrome版本相對應(yīng)的ChromeDriver
  • 安裝Selenium庫
  • 將下載好的瀏覽器驅(qū)動放在Python的安裝目錄下的Scripy目錄中

注意:使用Edge的驅(qū)動器會提示要將驅(qū)動添加到path中,可以在初始化一個Edge瀏覽器對象的時候傳入Edge驅(qū)動的路徑:

from selenium import webdriverbrowser = webdriver.Edge('E:\python\Scripts\msedgedriver.exe') browser.get('https://www.baidu.com')

所以建議大家使用Chrome瀏覽器。

ChromeDriver下載地址

Edge驅(qū)動下載地址

Selenium官方文檔


5.2.2 Selenium的使用

當(dāng)所有的準(zhǔn)備工作都完成后,打開編輯器,來敲代碼了。

首先來看看下面這個小例子:

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWaitbrowser = webdriver.Chrome() # 聲明一個chrome瀏覽器對象 try:browser.get('https://www.baidu.com') # 打開指定的網(wǎng)頁input = browser.find_element_by_id('kw') # 尋找搜索框input.send_keys('Python') # 在搜索框中輸入指定的內(nèi)容input.send_keys(Keys.ENTER)wait = WebDriverWait(browser, 10)wait.until(EC.presence_of_all_elements_located((By.ID, 'content_left')))print(browser.current_url) # 打印當(dāng)前頁面的urlprint(browser.get_cookies()) # 打印當(dāng)前頁面的cookiesprint(browser.page_source) # 打印當(dāng)前頁面的源代碼 finally:browser.close()

執(zhí)行上面的代碼,如果一切正常的話,你的電腦應(yīng)該自動打開了Chrome瀏覽器并來到了百度的首頁,然后自動在搜索框中輸入了“Python”并點擊了搜索按鈕,控制臺中打印出當(dāng)前頁面的url、cookie、頁面源代碼。


1. 聲明瀏覽器對象

Selenium支持非常多的瀏覽器,如Chrome、Firefox、Edge等,還有Android、BlackBerry等手機端的瀏覽器。

下面是初始瀏覽器的方法:

from selenium import webdriverbrowser = webdriver.Chrome() browser = webdriver.Firefox() browser = webdriver.Edge() browser = webdriver.PhantomJS() browser = webdriver.Safari()

注意:
可以指定驅(qū)動器路徑來初始化瀏覽器對象:

browser = webdriver.Edge(‘E:\python\Scripts\msedgedriver.exe’)


2. 訪問頁面

可以使用get()方法來請求網(wǎng)頁,將要請求的url傳入即可,下面是請求百度的例子:

from selenium import webdriver import timebrowser = webdriver.Edge('E:\python\Scripts\msedgedriver.exe') browser.get('https://www.baidu.com') print(browser.page_source) time.sleep(10) browser.close()

3. 查找節(jié)點

Selenium可以驅(qū)動瀏覽器完成各種操作,比如填充表單、模擬點擊等。比如,我們想要完成在某個輸入框輸入文本的操作,我們首先需要使用selenium查找到這個輸入框所在的節(jié)點位置。


  • 查找單個節(jié)點的常用方法

    查找單個節(jié)點的方法
    find_element_by_id()通過節(jié)點的id屬性值來查找單個節(jié)點
    find_element_by_name()通過節(jié)點的name屬性值來查找單個節(jié)點
    find_element_by_xpath()通過xpath來查找單個節(jié)點
    find_element_by_link_text()通過完整的鏈接文本(點擊該文本就會跳到另一個頁面)查找單個節(jié)點
    find_element_by_partial_link_text()通過部分鏈接文本來查找單個節(jié)點
    find_element_by_tag_name()通過節(jié)點的標(biāo)簽名來查找單個節(jié)點
    find_element_by_class_name()通過節(jié)點的class屬性值來查找單個節(jié)點
    find_element_by_css_selector()通過css來查找當(dāng)個節(jié)點
    find_element(By.ID,‘ ’)同find_element_by_id()
    find_element(By.CLASS_NAME, ‘ ’)同find_element_by_class_name()
    find_element(By.CSS_SELECTOR,’ ’)同find_element_by_css_selector()
    find_element(By.LINK_TEXT,’ ’)同find_element_by_link_text()
    find_element(By.NAME,’ ’)同find_element_by_name()
    find_element(By.PARTIAL_LINK_TEXT,’ ’)同find_element_by_partial_link_text()
    find_element(By.TAG_NAME,’ ’)同find_element_by_tag_name()
    find_element(By.XPATH,’ ’)同find_element_by_xpath()

例子:

from selenium import webdriver from selenium.webdriver.common.by import Bybrowser = webdriver.Chrome() url = 'https://www.taobao.com/' browser.get(url) print(browser.find_element(By.ID, 'q')) print(browser.find_element_by_id('q')) print(browser.find_element_by_xpath('//*[id="q"]')) print(broswer.find_element_by_css_selector('#q'))

運行結(jié)果:

<selenium.webdriver.remote.webelement.WebElement (session="5e8df8d577c9340c9524ecebcf924800", element="18f8aa32-46d6-43cd-89b1-67e48e314310")> <selenium.webdriver.remote.webelement.WebElement (session="5e8df8d577c9340c9524ecebcf924800", element="18f8aa32-46d6-43cd-89b1-67e48e314310")> <selenium.webdriver.remote.webelement.WebElement (session="5e8df8d577c9340c9524ecebcf924800", element="18f8aa32-46d6-43cd-89b1-67e48e314310")> <selenium.webdriver.remote.webelement.WebElement (session="5e8df8d577c9340c9524ecebcf924800", element="18f8aa32-46d6-43cd-89b1-67e48e314310")>

4. 查找多個節(jié)點

在網(wǎng)頁中如果查找的節(jié)點有多個,使用find_element()方法將只會找到第一個節(jié)點,如果想要查找多個節(jié)點,就需要使用find_elements()方法。

from selenium import webdriverwith webdriver.Chrome() as browser:browser.get('https://www.taobao.com')all_nodes = browser.find_elements_by_xpath('//li[@class="J_Cat a-all"]')print(len(all_nodes))print(all_nodes)

上面的代碼將自動使用Chrome打開淘寶的主頁,打印出查找到的淘寶主頁左上角的15個導(dǎo)航欄。

將上面的表格中查找單個節(jié)點的方法中的element改為elements就是查找多個節(jié)點的方法。


5. 節(jié)點交互

Selenium可以驅(qū)動瀏覽器來執(zhí)行一些操作,也就是可以讓瀏覽器執(zhí)行一些動作。

常用的有:輸入文字時用send_keys()方法,清空文字時用clear()方法,點擊時用click()方法。

from selenium import webdriver import timewith webdriver.Chrome() as browser:browser.get('https://www.taobao.com') # 打開鏈接input = browser.find_element_by_xpath('//*[@id="q"]') # 找到搜索框input.send_keys('背包') # 在搜索框中輸入背包time.sleep(5)input.clear() # 清空搜索框input.send_keys('書包') # 在搜索框中輸入書包search_button = browser.find_element_by_xpath('//button[@class="btn-search tb-bg"]') # 查找搜索按鈕time.sleep(5)search_button.click() # 點擊搜索按鈕

6. 動作鏈

上面的選擇輸入框、向輸入框中輸入文本、點擊按鈕等動作,都是有特定的執(zhí)行對象;但是,對于鼠標(biāo)移動、按盤按鍵等,這些動作由另一種方式來執(zhí)行,這就是動作鏈。

from selenium import webdriver from selenium.webdriver import ActionChains import timebrowser = webdriver.Chrome() browser.get('示例網(wǎng)站的url') browser.find_element_by_xpath('//input[@placeholder="請輸入郵箱"]').send_keys('jxd') time.sleep(1) browser.find_element_by_xpath('//input[@placeholder="請輸入密碼"]').send_keys('123456') time.sleep(1) browser.find_element_by_xpath('//div[@class="geetest_wait"]').click() time.sleep(1)# 更換監(jiān)視界面 ifame = browser.find_element_by_xpath('//div[@class="inner-conntent"]') browser.switch_to.frame(ifame) # 要拖動的元素 source = browser.find_element_by_xpath('//div[@class="geetest_slider_button"]') # 要拖動到的位置元素 target = browser.find_element_by_xpath('//div[@class="geetest_slider_tip geetest_fade"]') actions = ActionChains(browser) actions.drag_and_drop(source, target) actions.perform()

7. 滑動頁面

滑動頁面其實就是執(zhí)行js語句,可以將控制頁面滑動的js語句放在driver.execute_script(js語句)中來執(zhí)行:

driver.execute_script('window.scrollBy(0,1000)') # 滑動的距離,分為x軸和y軸driver.execute_script('window.scrollTo(0,1000)') # 滑動到指定的坐標(biāo)driver.execute_script("window.scrollTo(0,document.body.scrollHeight);") # 滑動到頁面的最下方driver.execute_script("document.getElementById('page').scrollIntoView(true)") # 將查找到的元素顯示在屏幕中間,scrollIntoView(false)就是將查找到的元素顯示在屏幕的底部

8. 執(zhí)行JavaScript

上面的向下滑動頁面就是執(zhí)行JavaScript的例子,我們可以使用driver.execute_script(javascript語句)來執(zhí)行JavaScript代碼。


9. 獲取節(jié)點的信息

方法作用
WebElement.get_attribute(‘屬性名’)獲取標(biāo)簽指定的屬性的屬性值
WebElement.text獲取標(biāo)簽的文本
WebElement.id獲取標(biāo)簽的id
WebElement.location獲取標(biāo)簽在頁面中的相對位置
WebElement.tag_name獲取標(biāo)簽的標(biāo)簽名
WebElement.size獲取標(biāo)簽的大小

10. 切換Frame

網(wǎng)頁中有一種節(jié)點叫做iframe,也就是子頁面,我們使用selenium提供的選擇節(jié)點的方法是在父級Frame里面操作,而如果頁面中有子頁面,它是不能獲取到子Frame中的節(jié)點的。此時,就需要使用switch_to.frame()方法來切換Frame,上面的例子中有。

注意:switch_to.frame()默認(rèn)接收的是目標(biāo)frame節(jié)點的id或name,如果目標(biāo)節(jié)點沒有id屬性和name屬性,那么就可以傳入一個用select_element_by_xpath()等方法定位到的WebElement對象。


11. 等待

有時我們請求的頁面中的元素或節(jié)點是通過Ajax加載的,就需要一定的時間,在元素未加載出來之前我們?nèi)ゲ檎以撛鼐蜁也坏?#xff0c;所以,就需要等待一段時間,等元素加載出來之后再執(zhí)行查找元素等一系列操作。


隱式等待:在查找節(jié)點而節(jié)點并沒有立即出現(xiàn)時,隱式等待會等待一段時間再查找節(jié)點,時間默認(rèn)是0秒,如果還未找到節(jié)點就會拋出節(jié)點未找到的異常。隱式等待可以看做是time.sleep()方法。

browser.imlicitly_wait(10) # 隱式等待10秒鐘

顯示等待:規(guī)定一個最長等待時間,在這段時間里如果查找到了節(jié)點就返回節(jié)點,如果在這段時間里還找到該節(jié)點,則拋出超時異常。

from selenium.webdriver.support import expected_conditions as ECwait = WebDriverWait(browser, 10) # 設(shè)置顯式等待時間是10秒 input = wait.until(EC.presence_of_element_located((By.ID, 'q')))

until()方法接收一個等待條件expected_conditions,上面的例子中的等待條件是presence_of_element_located(),指的是節(jié)點出現(xiàn)的意思,其參數(shù)是節(jié)點的定位元組,也就是ID為q的節(jié)點。


常見的等待條件

等待條件含義
title_is標(biāo)題是某內(nèi)容
title_contains標(biāo)題包含某內(nèi)容
presence_of_element_located節(jié)點加載出來,傳入定位元組,如(By.ID, ‘p’)
visibility_of_element_located節(jié)點可見,傳入定位元組
visibility_of節(jié)點可見,傳入節(jié)點對象
presence_of_all_elements_located所有節(jié)點加載出來
text_to_be_present_in_element某個節(jié)點文本包含某個文字
text_to_be_present_in_element某個節(jié)點值包含某個文字
frame_to_be_avaliable_and_switch_to_it加載并切換
invisibility_of_element_located節(jié)點不可見
element_to_be_clickable節(jié)點可點擊
staleness_of判斷 個節(jié)點是否仍在 DOM ,可判斷頁面是杏已經(jīng)刷新
element_ to_be_selected節(jié)點可選擇,傳節(jié)點對象
element_located_to_be_selected節(jié)點可選擇,傳人定位元組
element_selection_state_to_be傳人節(jié)點對象以及狀態(tài),相等返回 True ,否則返回 False
element_located_selection_state_to_be傳入定位元組以及狀態(tài),相等返回 True ,否則返回 False
alert_is_present是否出現(xiàn)警告

12. 控制頁面前進(jìn)和后退

from seleniun import webdriverbrowser.forward() # 前進(jìn) browser.back() # 后退

13. 對cookies的操作

from selenium import webdirverbrowser.get_cookies() # 返回字典類型的所有cookies browser.add_cookies() # 添加一個cookies,參數(shù)是字典類型 browser.delete_all_cookies() # 刪除所有的cookies

14. 選項卡

from selenium import webdriver import timebrowser = webdriver.Chrome() # 初始化一個瀏覽器對象browser.get('https://www.baidu.com') # 訪問百度 browser.execute_script('window.open()') # 新開啟一個選項卡 time.sleep(2)print(browser.window_handles) # 打印所有選項卡代號列表browser.switch_to.window(browser.window_handles[1]) # 更換到選項卡代號列表中的第一個選項卡 time.sleep(1)browser.get('https://www.taobao.com') browser.switch_to.window(browser.window_handles[0]) time.sleep(1)browser.get('https://python.org')

15. 模擬輸入鍵盤

上面講的sendkeys()方法可以向輸入框中輸入文字,它還可以實現(xiàn)模擬鍵盤的輸入,甚至是組合鍵。

from selenium.webdriver.common.keys import Keysdriver = webdriver.Firefox() driver.get([https://www.baidu.com](https://www.baidu.com/))el = driver.find_element(By.ID, "kw") # 找到輸入框 el.send_keys(“seleniumm”) # 在輸入框中輸入"seleniumm" el.send_keys(Keys.BACK_SPACE) # 模擬按一下Backspaece鍵 el.send_keys(Keys.SPACE) # 模擬按一下Space鍵 el.send_keys(“教程”) # 輸入"教程" el.send_keys(Keys.CONTROL, ‘a(chǎn)’) # 模擬按下 "a"鍵 el.send_keys(Keys.CONTROL, ‘x’) # 模擬按下 "x"鍵 el.send_keys(Keys.CONTROL, ‘v’) # 模擬按下 "v"鍵 el.send_keys(Keys.ENTER) # 模擬按下"enter"鍵

16. 異常處理

selenium的異常類型都在selenium.common.exceptions這個包中,下面列舉了常用的異常:

異常說明
NoSuchElementException未找到節(jié)點
NoSuchAttributeException節(jié)點沒有改屬性
NoSuchFrameExceptionframe未找到
NoSuchWindowExceptionwindow未找到

知道這些常用的異常之后,就可以使用try except來將這些異常捕獲并做相應(yīng)的處理了。


5.3 使用Selenium的例子

使用Selenium爬取手機信息


感謝你的閱讀!

總結(jié)

以上是生活随笔為你收集整理的动态网页的抓取的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。