selenium+Excel半自动化搜索答案
1. 背景
上一篇文章中我们介绍了如何使用ChromeDriverManager 来管理ChromeDriver
如何使用ChromeDriverManager 来管理ChromeDriver_friklogff的博客-CSDN博客
本篇文章着重记录爬虫解析与学习过程,测试数据收集与结果处理下一篇我们再说。
请注意,本文中的部分内容来自网络搜集和个人实践,如有任何错误,请随时向我们提出批评和指正。本文仅供学习和交流使用,不涉及任何商业目的。如果因本文内容引发版权或侵权问题,请通过私信告知我们,我们将立即予以删除。
2. 技术选择
- 使用Selenium控制Chrome浏览器爬取动态网页
- 使用BeautifulSoup解析HTML
- 使用OpenPyXL和XlsxWriter处理Excel文件
3. 实现过程
- 初始化ChromeDriver,使用ChromeDriverManager自动下载匹配chromedriver
- 实现一个get_answer方法
- 输入搜索题目
- 等待页面加载
- 使用BeautifulSoup解析页面
- 提取题目、答案、图片URL
- 读取Excel获取题目
- 调用get_answer获取每个题目的结果
- 将结果写入结果Excel
3.1 初始化ChromeDriver
使用ChromeDriverManager可以自动下载匹配Chrome版本的chromedriver,非常方便。
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
3.2 实现获取答案方法
def get_answer(question):
# 搜索题目
search_input.send_keys(question)
search_btn.click()
# 等待页面加载完成
WebDriverWait(driver, 10).until()
# 解析页面
soup = BeautifulSoup(driver.page_source, 'html.parser')
# 使用CSS选择器提取题目、答案
question = soup.select('.question')
answer = soup.select('.answer')
# 返回结果
return question, answer
这里使用CSS选择器提取信息,并使用WebDriverWait来等待页面元素加载。
3.3 读取Excel获取题目
使用openpyxl库读取Excel文件。
wb = openpyxl.load_workbook('questions.xlsx')
sheet = wb['Sheet1']
questions = [cell.value for cell in sheet['A']]
3.4 保存结果到Excel
使用xlsxwriter库创建新的Excel文件,并逐行写入结果。
workbook = xlsxwriter.Workbook('results.xlsx')
worksheet = workbook.add_worksheet()
for idx, qa in enumerate(question_answers):
worksheet.write(idx, 0, qa[0])
worksheet.write(idx, 1, qa[1])
workbook.close()
3.5 主要流程
# 初始化
driver = init_driver()
# 读取题目
questions = read_excel()
# 遍历爬取
results = []
for q in questions:
result = get_answer(q)
results.append(result)
# 保存结果
save_to_excel(results)
4. 关键点
- Selenium等待页面元素加载非常重要,这里使用WebDriverWait
- 使用CSS选择器提取信息,BeautifulSoup find方法
- Excel文件读写可以大批量处理题目
# -*- coding = utf-8 -*-
"""
# @Time : 2023/7/23 17:26
# @Author : FriK_log_ff 374591069
# @File : pc.py
# @Software: PyCharm
# @Function: 请输入项目功能
"""
import os
import time
import openpyxl
import xlsxwriter
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from collections import namedtuple
class AnswerScraper:
def __init__(self):
# 添加无头模式选项
# options = Options()
# options.add_argument("--headless")
# 获取当前文件所在目录的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
# 设置驱动下载目录为当前目录下的drivers文件夹
driver_path = os.path.join(current_dir, 'drivers')
# 创建目录 如果存在则跳过创建
os.makedirs(driver_path, exist_ok=True)
# 初始化driver,使用ChromeDriverManager下载匹配Chrome版本的驱动
self.driver = webdriver.Chrome(service=Service(ChromeDriverManager(path=driver_path).install()))
# 简单的测试用例
self.driver.get("https://tiku.baidu.com/buguakewap/browse/index?qid=undefined&limitSwitch=1&limitTimes=3")
# 初始化WebDriverWait对象,用于等待页面元素加载,等待10秒,等页面加载元素
self.wait = WebDriverWait(self.driver, 10)
def get_answer(self, search_question):
# 搜索问题
search_input = self.driver.find_element(By.CSS_SELECTOR,
"body > div.container-index > div.header > div > div.search > input[type=text]")
# 定位搜索框
search_input.click()
search_input.clear()
search_input.send_keys(search_question)
# 在搜索框输入搜索词
search_btn = self.driver.find_element(By.CSS_SELECTOR,
"body > div.container-index > div.header > div > div.search > div")
# 定位搜索按钮
search_btn.click()
# 等待页面加载
self.wait = WebDriverWait(self.driver, 10)
self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,
"body > div.container-index > div.main > div.content > div.quest > div.stem > div > p:nth-child(1) > span")))
# 解析答案
# htmls = self.driver.page_source
quests = self.driver.find_elements(By.CSS_SELECTOR, ".quest")
htmls = ''
questions = ''
answers = ''
img_urls = ''
for quest in quests:
html = quest.get_attribute('outerHTML')
htmls += html
soup = BeautifulSoup(htmls, 'html.parser')
# 提取问题
question = soup.find('div', class_='stem__content').text
questions += question
# 提取答案
answer = soup.find('div', class_='answer__content').text
answers += answer
# 提取图片
try:
img_url = soup.find('img').get('src')
img_urls += img_url
# img_urls.append(img_url)
except:
pass
time.sleep(4)
return [questions, answers, img_urls]
question_file = 'questions.xlsx'
result_file = 'results.xlsx'
# 读取题目
wb = openpyxl.load_workbook(question_file)
sheet = wb['Sheet1']
s_questions = [cell.value for cell in sheet['A'][1:]]
print(s_questions)
# 创建结果文件对象
workbook = xlsxwriter.Workbook(result_file)
worksheet = workbook.add_worksheet()
# 写入题目和答案
i = 0
for que in s_questions:
i += 1
scraper = AnswerScraper()
print(f'正在获取题目"{que}\n"')
result = scraper.get_answer(que)
print(f'正在写入题目"{result[0]}"的答案"{result[1]}{result[2]}\n"')
worksheet.write(i, 0, result[0])
worksheet.write(i, 1, result[1])
worksheet.write(i, 2, result[2])
workbook.close()
2023-08-31
最近chrome自动更新了116版本,chromedriver仍停留在114版本,以上代码会在当前目录自动下载最新版本chromedriver,只有当二者同步更新时可以正常使用
新文已发,完美解决二者未同步更新时产生的问题
自动化管理chromedriver-完美解决版本不匹配问题
国内使用chromedriver_autoinstaller网络受限,你可以在这里下载我下载好的chromedriver
链接:https://pan.baidu.com/s/1GnJTPO-4JPB_j2wrYZZJ8A?pwd=97jn
提取码:97jn
然后使用
service = Service("drivers/104/chromedriver.exe")
————————————————
版权声明:本文为CSDN博主「friklogff」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42531954/article/details/132613060
import os
import time
import openpyxl
import requests
import xlsxwriter
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from collections import namedtuple
class AnswerScraper:
def __init__(self):
# 添加无头模式选项
# options = Options()
# options.add_argument("--headless")
# 获取当前文件所在目录的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
# 设置驱动下载目录为当前目录下的drivers文件夹
driver_path = os.path.join(current_dir, 'drivers')
# 创建目录 如果存在则跳过创建
os.makedirs(driver_path, exist_ok=True)
# 初始化driver,使用ChromeDriverManager下载匹配Chrome版本的驱动
# self.driver = webdriver.Chrome(service=Service(ChromeDriverManager(path=driver_path).install()))
option = Options()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_argument('--disable-blink-features=AutomationControlled')
option.add_argument('--headless') # 启用无头模式
service = Service("drivers/104/chromedriver.exe")
self.driver = webdriver.Chrome(options=option, service=service)
# 简单的测试用例
self.driver.get("https://tiku.baidu.com/buguakewap/browse/index?qid=undefined&limitSwitch=1&limitTimes=3")
# 初始化WebDriverWait对象,用于等待页面元素加载,等待10秒,等页面加载元素
self.wait = WebDriverWait(self.driver, 10)
def get_answer(self, search_question):
# 搜索问题
search_input = self.driver.find_element(By.CSS_SELECTOR,
"body > div.container-index > div.header > div > div.search > input[type=text]")
# 定位搜索框
search_input.click()
search_input.clear()
search_input.send_keys(search_question)
# 在搜索框输入搜索词
search_btn = self.driver.find_element(By.CSS_SELECTOR,
"body > div.container-index > div.header > div > div.search > div")
# 定位搜索按钮
search_btn.click()
# 等待页面加载
self.wait = WebDriverWait(self.driver, 10)
self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,
"body > div.container-index > div.main > div.content > div.quest > div.stem > div > p:nth-child(1) > span")))
# 解析答案
# htmls = self.driver.page_source
quests = self.driver.find_elements(By.CSS_SELECTOR, ".quest")
htmls = ''
questions = ''
answers = ''
img_urls = ''
for quest in quests:
html = quest.get_attribute('outerHTML')
htmls += html
soup = BeautifulSoup(htmls, 'html.parser')
# 提取问题
question = soup.find('div', class_='stem__content').text
questions += question
# 提取答案
answer = soup.find('div', class_='answer__content').text
answers += answer
# 提取图片
try:
img_url = soup.find('img').get('src')
img_urls += img_url
# img_urls.append(img_url)
except:
pass
time.sleep(4)
return [questions, answers, img_urls]
question_file = 'questions.xlsx'
result_file = 'results.xlsx'
# 读取题目
wb = openpyxl.load_workbook(question_file)
sheet = wb['Sheet1']
s_questions = [cell.value for cell in sheet['A'][1:]]
print(s_questions)
# 创建结果文件对象
workbook = xlsxwriter.Workbook(result_file)
worksheet = workbook.add_worksheet()
# 写入题目和答案
i = 0
for que in s_questions:
i += 1
scraper = AnswerScraper()
print(f'正在获取题目"{que}\n"')
result = scraper.get_answer(que)
print(f'正在写入题目"{result[0]}"的答案"{result[1]}{result[2]}\n"')
worksheet.write(i, 0, result[0])
worksheet.write(i, 1, result[1])
worksheet.write(i, 2, result[2])
#
#
workbook.close()
question_file = ‘questions.xlsx’
result_file = ‘results.xlsx’
5. 总结
通过这个爬虫项目,掌握了如下技能:
- Selenium爬取动态网页
- BeautifulSoup解析HTML
- Excel文件读写
- 项目规划和框架设计
- 多种技术的组合运用
下一次我们来尝试批量格式化提取问题,更合理的进行测试数据收集与结果处理,
然后还可以考虑使用代理,多线程,数据库接入接入大语言模型等技术提高爬取效率和数据存储。