本阶段在模板的基础上增加自动化封装方法,包括获取网页源码,获取网页cookie,点击,控制浏览器,等等方法。
1.selelnium模板解释
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
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
import time
import os
class SeleniumCrawler:
"""
Selenium爬虫类,用于网页自动化操作和数据抓取
"""
def __init__(self, driver_path=None, headless=False,
disable_images=False, proxy=None,
disable_automation_control=True, implicit_wait=10):
"""
初始化Selenium爬虫
参数:
browser_type (str): 浏览器类型,支持'chrome',
driver_path (str): 浏览器驱动路径,如果为None则使用系统PATH中的驱动
headless (bool): 是否使用无头模式(不显示浏览器界面)
disable_images (bool): 是否禁用图片加载以提高性能
user_agent (str): 自定义User-Agent
proxy (str): 代理服务器地址,格式为'ip:port'
disable_automation_control (bool): 是否禁用自动化控制特征(反爬虫检测)
implicit_wait (int): 隐式等待时间(秒)
"""
self.browser_type = 'chrome'
self.driver_path = driver_path
self.driver = None
self.headless = headless
self.disable_images = disable_images
self.user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
self.proxy = proxy
self.disable_automation_control = disable_automation_control
self.implicit_wait = implicit_wait
# 初始化浏览器
self._init_browser()
def _init_browser(self):
"""
根据配置初始化浏览器
"""
if self.browser_type == 'chrome':
self._init_chrome()
else:
raise ValueError(f"不支持的浏览器类型: {self.browser_type},请使用'chrome'")
# 设置隐式等待时间
if self.driver:
self.driver.implicitly_wait(self.implicit_wait)
def _init_chrome(self):
"""
初始化Chrome浏览器
"""
options = Options()
# 无头模式配置
if self.headless:
options.add_argument('--headless')
options.add_argument('--disable-gpu')
# # 禁用图片加载
# if self.disable_images:
# options.add_argument('--blink-settings=imagesEnabled=false')
# 设置User-Agent
if self.user_agent:
options.add_argument(f'--user-agent={self.user_agent}')
# 设置代理
if self.proxy:
options.add_argument(f'--proxy-server={self.proxy}')
# 禁用自动化控制特征(反爬虫检测)
if self.disable_automation_control:
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
# 初始化Chrome浏览器
if self.driver_path:
service = Service(executable_path=self.driver_path)
self.driver = webdriver.Chrome(service=service, options=options)
else:
self.driver = webdriver.Chrome(options=options)
# 进一步防止被检测为自动化工具
if self.disable_automation_control:
self.driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {get: () => undefined})
"""
})
#获取url
def open_url(self, url):
"""
打开指定URL
参数:
url (str): 要访问的网页URL
"""
self.driver.get(url)
def close(self):
"""
关闭当前浏览器窗口
"""
if self.driver:
self.driver.close()
def quit(self):
"""
退出浏览器,释放所有资源
"""
if self.driver:
self.driver.quit()
self.driver = None
def get_page_source(self,url=None) -> str:
if url:
self.driver.get(url)
"""
获取指定URL的网页HTML源代码
参数:
url (str): 要访问的网页URL
返回:
str: 网页的HTML源代码,如果获取失败则返回None
"""
try:
# 访问URL
# 等待页面加载完成,可以根据特定元素的存在来判断
# 这里简单地等待页面完全加载
time.sleep(1)
# 获取页面源代码
page_source = self.driver.page_source
return page_source
except TimeoutException:
print(f"页面加载超时: {self.driver.current_url}")
return None
except Exception as e:
print(f"获取页面源代码时发生错误: {e}")
return None
def get_cookies(self,url = None) -> dict:
"""
获取当前页面的cookies,并以cookies[name] = cookies[value]的形式返回
返回:
dict: cookies字典,如果获取失败则返回None
对于cookies反爬可以用此手段
"""
time.sleep(1)
try:
if url:
self.driver.get(url)
# 获取所有cookies
cookies = self.driver.get_cookies()
# 将cookies转换为字典格式
cookies_dict = {}
for cookie in cookies:
cookies_dict[cookie['name']] = cookie['value']
return cookies_dict
except Exception as e:
print(f"获取cookies时发生错误: {e}")
return None
def send_keys(self, by, value, text, timeout=10):
"""
向指定元素发送文本
参数:
by (str): 元素定位方式(如ID、NAME、CLASS_NAME等)
value (str): 元素定位值
text (str): 要输入的文本
timeout (int): 等待元素出现的超时时间(秒)
返回:
bool: 如果操作成功返回True,否则返回False
"""
try:
by = 'By.'+by
# 设置显式等待
wait = WebDriverWait(self.driver, timeout)
#等待出现时点击
element = wait.until(EC.presence_of_element_located((eval(by), value)))
# 清空输入框并输入文本
element.clear()
element.send_keys(text)
return True
except TimeoutException:
print(f"元素未找到: {by} = {value}")
return False
except Exception as e:
print(f"输入文本时发生错误: {e}")
return False
def click_element(self, by, value, timeout=10):
"""
点击指定元素
参数:
by (str): 元素定位方式(如ID、NAME、CLASS_NAME等)
value (str): 元素定位值
timeout (int): 等待元素出现的超时时间(秒)
返回:
bool: 如果操作成功返回True,否则返回False
"""
try:
by = 'By.' + by
# 设置显式等待
wait = WebDriverWait(self.driver, timeout)
element = wait.until(EC.element_to_be_clickable((eval(by), value)))
# 点击元素
element.click()
return True
except TimeoutException:
print(f"元素未找到或不可点击: {by} = {value}")
return False
except Exception as e:
print(f"点击元素时发生错误: {e}")
return False
def execute_console_command(self, command):
"""
在浏览器控制台执行JavaScript命令
参数:
command (str): 要执行的JavaScript命令
返回:
执行命令的结果
"""
try:
# 执行JavaScript命令
result = self.driver.execute_script(command)
return result
except Exception as e:
print(f"执行JavaScript命令时发生错误: {e}")
return None
以上是初步封装的Selenium模板,教程来自于我另一篇文章
这里我作一下简述,selenium模板初始化解释
初始化Selenium 参数:
browser_type (str): 浏览器类型,支持'chrome', driver_path (str):
浏览器驱动路径,如果为None则使用系统PATH中的驱动
headless (bool): 是否使用无头模式(不显示浏览器界面)
disable_images (bool): 是否禁用图片加载以提高性能
user_agent (str): 自定义User-Agent
proxy (str): 代理服务器地址,格式为'ip:port'
disable_automation_control (bool): 是否禁用自动化控制特征(反爬虫检测) implicit_wait (int): 隐式等待时间(秒)
def _init_chrome(self):
此方法初始化浏览器,包括无头模式开启,禁用图片,设置UA,设置代理,伪装 禁用自动化控制特征(反爬虫检测),初始化Chrome浏览器,进一步防止被检测为自动化工具。
以下是封装的方法
def open_url(self, url): 开启浏览器
def close(self):关闭浏览器
def quit(self):退出浏览器
def get_page_source: 获取网页源码
def get_cookies 获取网页cookies 绕过安全产品反爬
def send_keys 填充,一般用于登录
def click_element点击, 用于翻页和登录等
def execute_console_command 浏览器控制台,一般用于下滑加载
2.封装scrapy自动化方法
第一步,
导入封装好的selenium模板

第二步,设置好是否开启自动化

第三步,封装selenium方法
def get_html(self, url=None):
if self.open_selenium:
return self.seleniumCrawler.get_page_source(url)
else:
raise '自动化未开启'
def scrapy_get_cookies(self, url):
if self.open_selenium:
return self.seleniumCrawler.get_cookies(url)
else:
raise '自动化未开启'''
def scrapy_click_element(self, by, value, timeout=10):
if self.open_selenium:
self.seleniumCrawler.click_element(by, value, timeout)
else:
raise '自动化未开启'''
def scrapy_execute_console_command(self,command):
if self.open_selenium:
self.seleniumCrawler.execute_console_command(command)
else:
raise '自动化未开启'''
def scrapy_send_keys(self, key, value):
if self.open_selenium:
self.seleniumCrawler.send_keys(key, value)
else:
raise '自动化未开启'''
def scrapy_oepn_url(self,url):
if self.open_selenium:
self.seleniumCrawler.open_url(url)
else:
raise '自动化未开启'''
def scrapy_close_url(self,url):
if self.open_selenium:
self.seleniumCrawler.close()
else:
raise '自动化未开启'''
selenium对于爬虫基本比较重要的方法就这些。
框架源代码
python
import json
from scrapy import Request
import scrapy
from scrapy import FormRequest
from scrapy.http import JsonRequest
import scrapy
from myspider.selenium_tem.selenium_tem import SeleniumCrawler
class superspider(scrapy.Spider):
def_headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"
} # 默认请求头
custom_settings = {} # 初始设置
start_page = 1 # 起始翻页数
cookie_dict = None # 设置cookies
allowed_domains = [] # 允许域名
max_page = 1 # 最大翻页数
start_urls = [] # 单个爬虫脚本请求列表
open_selenium = False # 是否开启自动化
SeleniumCrawler = None
def __init__(self, **kwargs):
super(superspider, self).__init__(**kwargs)
super().__init__(**kwargs)
if self.open_selenium:
self.seleniumCrawler = SeleniumCrawler()
def start_requests(self):
# 爬虫开始前准备
self.gen_source_necessary_info()
for params in self.start_urls:
params['page'] = self.start_page
yield from self.getListData(params)
def getListData(self, params):
if params.get('method') == 'POST':
if params.get('payload'):
for i in range(self.start_page, self.max_page + 1):
params['payload'][str(params['f_page'])] = str(i)
print(params['payload'])
yield self.post(url=params['url'], callback=self.parse, cookies=self.cookie_dict,
headers=self.def_headers,
meta={'params': params}, payload=eval(self.url_rule(params)) or params['payload'])
else:
for i in range(self.start_page, self.max_page + 1):
params['data'][str(params['f_page'])] = str(i)
print(params['data'])
yield self.post(url=params['url'], callback=self.parse, cookies=self.cookie_dict,
headers=self.def_headers,
meta={'params': params}, data=eval(self.url_rule(params)) or params['data'])
else:
for i in range(self.start_page, self.max_page + 1):
yield self.get(url=eval(self.url_rule(params)) or params['url'].format(i), callback=self.parse,
cookies=self.cookie_dict, meta={'params': params},
headers=self.def_headers)
def get(self, url, headers=None, cookies=None, callback=None, meta=None, dont_filter=True, cb_kwargs=None):
return Request(url=url, headers=self.def_headers, cookies=self.cookie_dict, callback=callback, meta=meta,
dont_filter=dont_filter,
cb_kwargs=cb_kwargs or {})
def post(self, url, headers=None, cookies=None, callback=None, meta=None, data=None, dont_filter=True, payload=None,
cb_kwargs=None):
if payload:
return JsonRequest(url=url, headers=headers, cookies=cookies,
callback=callback, meta=meta, method='POST', data=payload, dont_filter=dont_filter,
cb_kwargs=cb_kwargs or {}
)
if data:
return scrapy.FormRequest(url=url, headers=headers, cookies=cookies,
callback=callback, meta=meta, method='POST', formdata=data,
dont_filter=dont_filter,
cb_kwargs=cb_kwargs or {}
)
def gen_source_necessary_info(self):
pass
def parse(self, response, **kwargs):
pass
def url_rule(self, params):
return "None"
def get_html(self, url=None):
if self.open_selenium:
return self.seleniumCrawler.get_page_source(url)
else:
raise '自动化未开启'
def scrapy_get_cookies(self, url):
if self.open_selenium:
return self.seleniumCrawler.get_cookies(url)
else:
raise '自动化未开启'''
def scrapy_click_element(self, by, value, timeout=10):
if self.open_selenium:
self.seleniumCrawler.click_element(by, value, timeout)
else:
raise '自动化未开启'''
def scrapy_execute_console_command(self,command):
if self.open_selenium:
self.seleniumCrawler.execute_console_command(command)
else:
raise '自动化未开启'''
def scrapy_send_keys(self, key, value):
if self.open_selenium:
self.seleniumCrawler.send_keys(key, value)
else:
raise '自动化未开启'''
def scrapy_oepn_url(self,url):
if self.open_selenium:
self.seleniumCrawler.open_url(url)
else:
raise '自动化未开启'''
def scrapy_close_url(self):
if self.open_selenium:
self.seleniumCrawler.close()
else:
raise '自动化未开启'''
3.案例
还是以豆瓣为例,豆瓣比较简单,一般不用自动化。

首先看豆瓣的翻页规律,
所以我们可以用xpath定位
self.scrapy_click_element('XPATH', f'.//a[@href = "?start={(i) * 25}&filter="]')

selenium基本的流程

结果如下:

自动化非常的好用。降低逆向的技术栈,但是,对于每日更新大量数据,或者会弹出大量验证码,或者有检测自动化工具的网站。自动化没用,说实话,这篇文章重点讲爬虫框架构成,不是selenium。我就业时,遇到的网站,基于服务器上,selenium根本没法解决,很不稳定,基本爬不了多少数据,甚至不能运行(因为线上有并发多个爬虫脚本,如果都是自动化,相当于后台开启几百个浏览器,CPU爆满)所以以前觉得有selenium等自动化工具存在,有必要学逆向吗?直到真正就业时,真正遇到大站点网站时,我才觉得selenium局限性大,逆向才是真王道。