今天在使用selenium爬取 中國執(zhí)行信息公開網(wǎng)的時候遇到了一個問題:
明明瀏覽器已經(jīng)訪問了,但是還是一直不進(jìn)行下一步動作,而是一直在加載,在網(wǎng)上找了很多答案后,發(fā)現(xiàn)原來selemim會等網(wǎng)站的所有元素都加載完畢才會執(zhí)行后面的操作,如此一來我們的程序就會一直阻塞相當(dāng)長的一段時間,這顯然不是我們想要的,那么該如何解決呢?
其實(shí)很簡單!
使用set_page_load_timeout這個方法設(shè)置一個超時時間即可,代碼如下:
from selenium import webdriver
browser = webdriver.Chrome() # 實(shí)例化一個瀏覽器對象
browser.set_page_load_timeout(5) # 設(shè)置超時時間為5秒,如果5秒后網(wǎng)頁還是沒有加載完成則拋出異常
try:
browser.get(url) # 請求 url
except TimeoutException: # 捕獲超時異常
print("超時跳過")
這時可能會導(dǎo)致一個情況:就是超過了5秒我們自己想要處理定位的元素也沒有加載出來怎么辦?
我使用了selenium的顯式等待帶處理這個問題(其實(shí)不用也可以,直接捕獲異常重新處理即可)
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser = webdriver.Chrome() # 實(shí)例化一個瀏覽器對象
browser.set_page_load_timeout(5) # 設(shè)置超時時間為5秒,如果5秒后網(wǎng)頁還是沒有加載完成則拋出異常
try:
browser.get(url) # 請求 url
except TimeoutException: # 捕獲超時異常
print("超時跳過")
wait = WebDriverWait(browser, 6) # 設(shè)置顯式等待對象,若6秒還未加載出來則拋出異常
input_name = wait.until(EC.presence_of_element_located((By.ID, 'pName'))) # 定位姓名輸入框
input_usr_id = wait.until(EC.presence_of_element_located((By.ID, 'pCardNum'))) # 定位證件號輸入框
input_captcha = wait.until(EC.presence_of_element_located((By.ID, 'yzm'))) # 定位驗(yàn)證碼輸入框
以下是這個方法的代碼,這是其中爬取頁面源碼的部分,新手學(xué)習(xí),僅供參考:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from chaojiying_Python.chaojiying import Chaojiying_Client # 對接的是超級鷹打碼平臺
from PIL import Image
import time
import random
import pymysql
from lxml import etree
import csv
import json
class Zxgk_spider:
def __init__(self, url, conn):
self.url = url
self.conn = conn
def read_csv(self):
'''
讀取csv文件
:return:
'''
l = []
with open('name.csv') as f: # 這個文件是要爬取的人員名單
reader = csv.reader(f)
for row in reader:
l.append(row)
return l
def post_content(self, name, usr_id):
url = self.url
browser = webdriver.Chrome()
browser.maximize_window() # 最大化瀏覽器
im_id = 0 # 圖片id初始設(shè)置為0,這個是用來
flag = 0
while flag < 5:
try:
browser.set_page_load_timeout(5)
try:
browser.get(url)
except TimeoutException:
print("超時跳過")
wait = WebDriverWait(browser, 6)
input_name = wait.until(EC.presence_of_element_located((By.ID, 'pName')))
input_usr_id = wait.until(EC.presence_of_element_located((By.ID, 'pCardNum')))
input_captcha = wait.until(EC.presence_of_element_located((By.ID, 'yzm')))
button_search = browser.find_element_by_class_name('btn.btn-zxgk.btn-block')
input_name.clear()# 清空輸入框
input_usr_id.clear()# 清空輸入框
input_name.send_keys(name)
input_usr_id.send_keys(usr_id)
input_captcha.send_keys("1234") # 當(dāng)開始輸入驗(yàn)證碼時,驗(yàn)證碼圖片會刷新,所以先輸入然后再清空,防止驗(yàn)證碼圖片改變,起到提前刷新一下驗(yàn)證碼的作用
input_captcha.clear()# 清空以便輸入
time.sleep(random.uniform(2.5, 2.8))
self.save_captcha(browser) # 截取驗(yàn)證碼
captcha_result = self.get_captcha_result() # 使用打碼平臺獲取驗(yàn)證碼的值
pic_str = captcha_result['pic_str']
im_id = captcha_result['pic_id']
print(pic_str)
print(type(pic_str))
input_captcha.send_keys(pic_str) # 將打碼平臺打好的驗(yàn)證碼輸入驗(yàn)證碼框中
time.sleep(random.uniform(1.5, 1.8)) # 延遲1.5到1.8秒,讓網(wǎng)頁反應(yīng)一下
button_search.click() # 點(diǎn)擊查詢按鈕
time.sleep(random.uniform(1.5, 1.8))
button_check = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'View')))# 此時瀏覽器出現(xiàn)了查看按鈕
try:
button_check.click() # 點(diǎn)擊查看
except TimeoutException:
print("超時跳過")
time.sleep(random.uniform(3.5, 3.8))
# 此時瀏覽器出現(xiàn)了第二個標(biāo)簽,我們想要的數(shù)據(jù)就在這個標(biāo)簽上,切換到第二個標(biāo)簽
browser.switch_to.window(browser.window_handles[1])
html_source = browser.page_source
# 若成功
flag = 1000 # 成功了將flag設(shè)為大于5的數(shù)即可,此時跳出while循環(huán)
except Exception as e:
print("捕獲異常:{}".format(e))
self.ReportError(im_id)
flag += 1
print("{}第{}次爬取失敗".format(name, flag))
if flag >= 5:
self.insert_into_url_mysql(name, usr_id, flag) # 當(dāng)爬取5次后失敗時,把未爬取成功的數(shù)據(jù)存入表中,等待后續(xù)處理
print("獲取失敗,將url存入數(shù)據(jù)庫")
# flag = 0
time.sleep(flag) # 延遲一下,失敗次數(shù)越多,延遲的時間越長
html_source = None # 若五次均失敗,則返回None
browser.close()# 關(guān)閉網(wǎng)頁
browser.quit()# 關(guān)閉瀏覽器
return html_source # 返回爬取的頁面源碼
def run(self):
# 獲取信息
reader = self.read_csv()
for row in reader:
name = row[1]
usr_id = row[3]
# 打開頁面輸入信息,點(diǎn)擊查看按鈕,獲取當(dāng)前頁面源碼
html_source = self.post_content(name, usr_id)
if html_source == None:
continue
else:
pass
if __name__ == '__main__':
conn = pymysql.connect(
host="127.0.0.1",
port=3306,
user="user",
password="xxxx",
database="database_name",
charset="utf8"
)
url = "http://zxgk.court.gov.cn/zhzxgk/"
zxgk = Zxgk_spider(url, conn)
zxgk.run()