今天在使用selenium爬取 中国执行信息公开网的时候遇到了一个问题:
明明浏览器已经访问了,但是还是一直不进行下一步动作,而是一直在加载,在网上找了很多答案后,发现原来selemim会等网站的所有元素都加载完毕才会执行后面的操作,如此一来我们的程序就会一直阻塞相当长的一段时间,这显然不是我们想要的,那么该如何解决呢?
其实很简单!
使用set_page_load_timeout
这个方法设置一个超时时间即可,代码如下:
from selenium import webdriver
browser = webdriver.Chrome() # 实例化一个浏览器对象
browser.set_page_load_timeout(5) # 设置超时时间为5秒,如果5秒后网页还是没有加载完成则抛出异常
try:
browser.get(url) # 请求 url
except TimeoutException: # 捕获超时异常
print("超时跳过")
这时可能会导致一个情况:就是超过了5秒我们自己想要处理定位的元素也没有加载出来怎么办?
我使用了selenium的显式等待带处理这个问题(其实不用也可以,直接捕获异常重新处理即可)
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser = webdriver.Chrome() # 实例化一个浏览器对象
browser.set_page_load_timeout(5) # 设置超时时间为5秒,如果5秒后网页还是没有加载完成则抛出异常
try:
browser.get(url) # 请求 url
except TimeoutException: # 捕获超时异常
print("超时跳过")
wait = WebDriverWait(browser, 6) # 设置显式等待对象,若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'))) # 定位验证码输入框
以下是这个方法的代码,这是其中爬取页面源码的部分,新手学习,仅供参考:
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初始设置为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") # 当开始输入验证码时,验证码图片会刷新,所以先输入然后再清空,防止验证码图片改变,起到提前刷新一下验证码的作用
input_captcha.clear()# 清空以便输入
time.sleep(random.uniform(2.5, 2.8))
self.save_captcha(browser) # 截取验证码
captcha_result = self.get_captcha_result() # 使用打码平台获取验证码的值
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) # 将打码平台打好的验证码输入验证码框中
time.sleep(random.uniform(1.5, 1.8)) # 延迟1.5到1.8秒,让网页反应一下
button_search.click() # 点击查询按钮
time.sleep(random.uniform(1.5, 1.8))
button_check = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'View')))# 此时浏览器出现了查看按钮
try:
button_check.click() # 点击查看
except TimeoutException:
print("超时跳过")
time.sleep(random.uniform(3.5, 3.8))
# 此时浏览器出现了第二个标签,我们想要的数据就在这个标签上,切换到第二个标签
browser.switch_to.window(browser.window_handles[1])
html_source = browser.page_source
# 若成功
flag = 1000 # 成功了将flag设为大于5的数即可,此时跳出while循环
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) # 当爬取5次后失败时,把未爬取成功的数据存入表中,等待后续处理
print("获取失败,将url存入数据库")
# flag = 0
time.sleep(flag) # 延迟一下,失败次数越多,延迟的时间越长
html_source = None # 若五次均失败,则返回None
browser.close()# 关闭网页
browser.quit()# 关闭浏览器
return html_source # 返回爬取的页面源码
def run(self):
# 获取信息
reader = self.read_csv()
for row in reader:
name = row[1]
usr_id = row[3]
# 打开页面输入信息,点击查看按钮,获取当前页面源码
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()