python+selenium+bs4爬取百度文庫內文字 && selenium 元素可以定位到,但是無法點選問題 && pycharm多行縮排、左移
先說一下可能用到的一些python知識
一、python中使用的是unicode編碼, 而日常文字使用各類編碼如:gbk utf-8 等等所以使用python進行文字讀寫操作時候經常會出現各種錯誤, 一般都是操作時沒有進行轉碼操作.而轉碼則需要decode(解碼)和encode(編碼)方法.
如:
str1.decode(‘gbk’), 表示將gbk編碼的字串‘str1’轉換成unicode編碼.
str2.encode(‘gbk’), 表示將unicode編碼的字串‘str2’轉換gbk編碼.
二、寫入資料的時候報錯程式直接停止,這就不得不重視“Python UnicodeEncodeError: 'gbk' codec can't encode character ”解決方法
將網路資料流寫入檔案時時,我們會遇到幾個編碼:
1: #encoding='XXX' 這裡(也就是python檔案第一行的內容)的編碼是指該python指令碼檔案本身的編碼,無關緊要。只要XXX和檔案本身的編碼相同就行了。 比如notepad++ "格式"選單裡面裡可以設定各種編碼,這時需要保證該選單裡設定的編碼和encoding XXX相同就行了,不同的話會報錯
2:網路資料流的編碼 比如獲取網頁,那麼網路資料流的編碼就是網頁的編碼。需要使用decode解碼成unicode編碼。
3:目標檔案的編碼 要將網路資料流的編碼寫入到新檔案,那麼我麼需要指定新檔案的編碼。在windows下面,新檔案的預設編碼是gbk,這樣的話,python直譯器會用gbk編碼去解析我們的網路資料流txt,然而txt此時已經是decode過的unicode編碼,這樣的話就會導致解析不了,出現上述問題。 解決的辦法就是,改變目標檔案的編碼:
f = open("out.html","w",encoding='utf-8')
三、pycharm縮排
1、pycharm使多行程式碼同時縮排、左移
滑鼠選中多行程式碼後,按下Tab鍵,一次縮排四個字元
2、pycharm使多行程式碼同時左移
滑鼠選中多行程式碼後,同時按住shift+Tab鍵,一次左移四個字元
四、time.sleep(t)
引數:t -- 推遲執行的秒數。
五、selenium 元素可以定位到,但是無法點選問題
描述:頁面元素可以定位到,但是無法點選click。元素可能被一個透明div覆蓋了
解決方案:
1.在執行click之前多休眠幾秒
2.確認自己的元素是否定位正確,是否有id,name,class相同的元素,加下劃線的是遮擋的div確定它的位置判斷他的z_index是否大於你要點選元素的z_index
4、將頁面拖拽到要點選的元素位置,例如百度文庫點選繼續閱讀展示全部內容(程式碼如下)
from selenium import webdriver from selenium.webdriver.common.keys import Keys driver = webdriver.Chrome('D:/chromedriver.exe') driver.get("https://wenku.baidu.com/view/aa31a84bcf84b9d528ea7a2c.html") page = driver.find_element_by_xpath("//*[@id='html-reader-go-more']/div[2]/div[1]/span/span[2]") driver.execute_script('arguments[0].scrollIntoView();', page) #拖動到可見的元素去 driver.find_element_by_xpath("//*[@id='html-reader-go-more']/div[2]/div[1]/p").click()
六、爬取百度文庫連線:https://wenku.baidu.com/view/df34290a763231126edb11f9.html
原本我就沒有想著要去用自動化工具去爬取,本來想著取用requests模擬請求,頂多就是麻煩一下弄弄js,但是我一看百度文庫它的請求頭
找這個檔案找了半天,主要是它的文字不是連續的,我剛開始大致一看都沒有找到。我還以為怎麼了(翻車現場)。。。弄了半天可以確定0.png?這樣型別的傳遞的是文庫的照片,0.json傳遞的是文庫的文字
但是這個請求頭的url太長了,,突然就不想用requests模擬請求了
那就用selenium自動化工具+bs4解析頁面,如果沒有安裝python的selenium庫和selenium對應的瀏覽器驅動可以看一下:安裝python的selenium庫和驅動
接下來我們把思路和程式碼說一下
1、首先匯入一下需要用到的模組
from selenium import webdriver from bs4 import BeautifulSoup from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time
2、因為這個頁面是動態的,我們的selenium檢測到瀏覽器框架之後就會返回原始碼,但是它不會去檢測這個頁面的動態載入部分是否加載出來,所以我們需要要求它去檢測一下
這兩個東西就是表示的是百度文庫中文庫是第幾頁,上圖表示的是百度文庫的第二頁的div元素,第三頁如下
這樣我就可以確定,這個肯定可以作為檢測條件
num = input('輸入總頁數:') st = "pageNo-" st_nums = st+str(num) #先構建一下最後一頁的屬性值
3、使用selenium模擬瀏覽器,並開啟指定網址
browser = webdriver.Chrome("D:\python-senium\chromedriver.exe")#裡面傳的引數是你selenium驅動所在位置 browser.get('https://wenku.baidu.com/view/df34290a763231126edb11f9.html') #傳送請求
4、我們使用selenium中的顯示等待,初始化最長等待時間為10s。並等待我們要點選“繼續閱讀”出現,然後將瀏覽器頁面移動到這裡
wait = WebDriverWait(browser,10) time.sleep(5) wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#html-reader-go-more > div.continue-to-read > div.banner-more-btn > span')))#等待條件:找到文庫中“繼續閱讀”字樣,並等待其出現 page = browser.find_element_by_xpath("//*[@id='html-reader-go-more']/div[2]/div[1]/span") #找到頁面中“繼續閱讀”所在位置 #js = "document.getElementsByClassName('banner-more-btn').style.visibility='hidden'" #browser.execute_script(js) #這個js程式碼是我原來以為是“繼續閱讀”被一個空的div包裹所以不能點選,然後我嘗試把這個div掩蓋掉,結果js程式碼執行失敗。。。 browser.execute_script('arguments[0].scrollIntoView();', page) #拖動到可見的元素“繼續閱讀”去
5、等待“繼續閱讀”可以點選就點選它,然後等待文庫中最後一頁也加載出來就返回頁面原始碼
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#html-reader-go-more > div.continue-to-read > div.banner-more-btn > span'))).click() wait.until(EC.presence_of_element_located((By.ID,st_nums))) #等待文庫中最後一頁也加載出來 html = browser.page_source
6、我們發現這些文字都被一個class屬性值為“ie-fix”所包裹,那我們就把它所包裹的p標籤都拿出來
its_p = soup.select(".ie-fix p")
然後對這個列表進行遍歷,並輸出其中的文字,並寫入檔案ab.txt中
soup = BeautifulSoup(html,"html.parser") #使用python內建解析html庫 def get_context(): try: its_p = soup.select(".ie-fix p") for it_p in its_p: print(it_p.text,end='') with open('ab.txt','a',encoding='utf-8') as f: f.write(it_p.text) except: print('出錯了') get_context() #呼叫函式 browser.close() #關閉瀏覽器
全部程式碼:
from selenium import webdriver from bs4 import BeautifulSoup from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time num = input('輸入總頁數:') st = "pageNo-" st_nums = st+str(num) '''''' browser = webdriver.Chrome("D:\python-senium\chromedriver.exe") browser.get('https://wenku.baidu.com/view/df34290a763231126edb11f9.html') wait = WebDriverWait(browser,10) time.sleep(5) wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#html-reader-go-more > div.continue-to-read > div.banner-more-btn > span'))) page = browser.find_element_by_xpath("//*[@id='html-reader-go-more']/div[2]/div[1]/span") #js = "document.getElementsByClassName('banner-more-btn').style.visibility='hidden'" #browser.execute_script(js) browser.execute_script('arguments[0].scrollIntoView();', page) #拖動到可見的元素去 wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#html-reader-go-more > div.continue-to-read > div.banner-more-btn > span'))).click() wait.until(EC.presence_of_element_located((By.ID,st_nums))) html = browser.page_source soup = BeautifulSoup(html,"html.parser") def get_context(): try: its_p = soup.select(".ie-fix p") for it_p in its_p: print(it_p.text,end='') with open('ab.txt','a',encoding='utf-8') as f: f.write(it_p.text) except: print('出錯了') get_context() browser.close()
結果:
缺陷:
這個程式碼不會去爬取文庫中圖片資訊,所以要是爬取ppt等文庫還是不要用了(後面爬ppt的我會再寫一篇部落格)
提示:
也是後代碼會執行出錯,主要原因是time.sleep()的時間不夠長,可以根據自身情況調整,或者可以多執行幾次(如果有其他好的方法可以,希望大佬可以帶帶我^_^)