因为CNVD官网采用了反爬机制,所以使用selenium能够更容易的爬取漏洞数据

1、在Windows中使用

注意根据chrome版本下载对应chromedriver

2、在无界面的Linux中使用

因为对于爬虫的识别,无头模式相对于有头模式特征多,所以尽量使用有头模式,在无界面Linux中使用有头模式需要安装Xvfb。对于cnvd,目前使用无头模式即可,可不需要安装xvfb。

yum install Xvfb -y

yum install xorg-x11-fonts* -y

有头模式不能添加add_argument('--headless'),如果使用无头模式则添加这一项。

安装Xvfb后可能会提示“DevToolsActivePort文件不存在”,那么添加options.add_argument('--no-sandbox')。

使用Xvfb启动:

xvfb-run python3 cnvd_download.py

3、对于各式各样的验证码最好的方法就是对接第三方打码平台,使用pytesseract需要pip安装pytesseract库,而且安装tesseract-ocr-w64-setup-v5.2.0.20220712.exe,并且别忘了添加环境变量。

使用ddddocr库识别库比较高,但只试了字母的简单验证码,其他验证码不清楚。

### selenium使用的版本为1.141.0
### Python版本为3.8.12
import os
import random
import sys
import time
from configparser import ConfigParser
from io import BytesIO
import ddddocr
from PIL import Image
# from pytesseract import pytesseract
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException # 读取配置文件信息
cf = ConfigParser()
cf.read('config.ini') sys_path = os.path.abspath(".") def get_config_data(target):
cnnvd_filed = {}
for k, v in cf.items(target):
cnnvd_filed[k] = v
return cnnvd_filed class DownloadCnvd(object):
def __init__(self):
# 从配置文件获取下载文件存放目录
self.download_path = get_config_data('CNVDPATH')['download_path']
# 从配置文件获取url
self.url = get_config_data('CNVDURL')['url']
# 登录CNVD官网的账号邮箱
self.login_email = get_config_data('CNVDLOGIN')['email']
# 登录CNVD官网的账号密码
self.login_password = get_config_data('CNVDLOGIN')['password']
options = webdriver.ChromeOptions()
# 配置下载文件存放目录
prefs = {'profile.default_content_settings.popups': 0,
'download.default_directory': os.path.join(sys_path, self.download_path)}
options.add_experimental_option('prefs', prefs)
# 修改windows.navigator.webdriver,防机器人识别机制,selenium自动登陆判别机制
options.add_experimental_option('excludeSwitches', ['enable-automation'])
# 禁止策略化
options.add_argument('disable-infobars')
# 当在Linux中使用xvfb进行有头操作时,此行配置解决DevToolsActivePort文件不存在的报错
options.add_argument('--no-sandbox')
#无头模式
options.add_argument('--headless)
options.add_argument('--ignore-certificate-errors')
options.add_argument("--disable-web-security")
# Linux中运行的配置,浏览器配置文件夹路径
options.add_argument('--user-data-dir=/home/ubuntu/.config/google-chrome')
# Windows中运行的配置,浏览器配置文件夹路径
#options.add_argument(r'--user-data-dir=C:\Users\Leeeee\AppData\Local\Google\Chrome\User Data')
# Linux中运行的配置, chromedriver的位置
self.driver = webdriver.Chrome(executable_path='/usr/bin/chromedriver', chrome_options=options)
#self.driver = webdriver.Chrome(executable_path='chromedriver.exe', chrome_options=options)
self.driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
}) # 使用pytesseract库进行识别图片验证码,不过识别率感人
def get_code(self):
os.remove(code_path)
element = self.driver.find_element_by_id('codeSpan') # 定位验证码图片
# 获取验证码图片在网页中的位置
left = int(element.location['x']) # 获取图片左上角坐标x
top = int(element.location['y']) # 获取图片左上角y
right = int(element.location['x'] + element.size['width']) # 获取图片右下角x
bottom = int(element.location['y'] + element.size['height']) # 获取图片右下角y
# 通过Image处理图像
code_path = os.path.join(sys_path, self.download_path) + 'img' + '.png'
self.driver.save_screenshot(code_path) # 截取当前窗口并保存图片
im = Image.open(code_path) # 打开图片
im = im.crop((left, top, right, bottom)) # 截图验证码
im.save(code_path) # 保存验证码图片
verityCode = Image.open(code_path)
code = pytesseract.image_to_string(verityCode)
return code # 在Linux中获取验证码图片并识别验证码,使用ddddocr库进行图片验证码识别
def get_code2(self):
element = self.driver.find_element_by_id('codeSpan') # 定位验证码图片
# 获取图片验证码的请求地址
img_path0 = element.get_attribute('src')
url = img_path0
print(url)
time.sleep(1)
# 打开新的页面,url为图片验证码的请求地址,应该是分辨率的问题,在登陆页直接截图获得验证码图片的是白灰方格,不是正常验证码图片,所以。。。
newTab = f'window.open("{url}");'
self.driver.execute_script(newTab)
self.driver.switch_to.window(self.driver.window_handles[-1])
element2 = self.driver.find_element_by_xpath('/html/body/img')
left = int(element2.location['x']) # 获取图片左上角坐标x
top = int(element2.location['y']) # 获取图片左上角y
right = int(element2.location['x'] + element2.size['width']) # 获取图片右下角x
bottom = int(element2.location['y'] + element2.size['height']) # 获取图片右下角y
code_image = self.driver.get_screenshot_as_png()
code_png = Image.open(BytesIO(code_image)) # 打开图片
code_png = code_png.crop((left, top, right, bottom)) # 截图验证码
code_png.save('code_png.png')
my_ocr = ddddocr.DdddOcr()
with open('code_png.png', 'rb') as f:
code_img_bytes = f.read()
code = my_ocr.classification(code_img_bytes)
# 切换标签页为登录页面
self.driver.switch_to.window(self.driver.window_handles[0])
print(code)
return code def get_code1(self):
element = self.driver.find_element_by_id('codeSpan') # 定位验证码图片
# 获取验证码图片在网页中的位置
left = int(element.location['x']) # 获取图片左上角坐标x
top = int(element.location['y']) # 获取图片左上角y
right = int(element.location['x'] + element.size['width']) # 获取图片右下角x
bottom = int(element.location['y'] + element.size['height']) # 获取图片右下角y
# img = conn.get(img_url)
# 通过Image处理图像
code_path = os.path.join(sys_path, self.download_path)+ 'img' + '.png' # 生成随机文件名
# self.driver.save_screenshot(code_path) # 截取当前窗口并保存图片
# im = Image.open(code_path) # 打开图片
# im = im.crop((left, top, right, bottom)) # 截图验证码
# im.save(code_path) # 保存验证码图片
code_image = self.driver.get_screenshot_as_png()
code_png = Image.open(BytesIO(code_image)) # 将图片读入内存中
code_png = code_png.crop((left, top, right, bottom)) # 截图验证码
code_png.save(code_path)
my_ocr = ddddocr.DdddOcr()
with open(code_path, 'rb') as f:
code_img_bytes = f.read()
code = my_ocr.classification(code_img_bytes)
os.remove(code_path)
print(code)
return code # 点击文件进行下载,一页下载十个文件
def get_file(self, flag):
file_count = 10
if flag == 1:
file_count = 1
num = 1
while num <= file_count:
file = self.driver.find_element_by_xpath(
'/html/body/div[4]/div[1]/div/div[2]/table/tbody/tr[{}]/td[1]/a'.format(num))
file.click()
num += 1
time1 = random.random()
time2 = random.randint(1, 3)
time.sleep(time1 + time2) # 获取“下一页”按钮并点击进行翻页
def get_next_page(self):
try:
page = self.driver.find_element_by_class_name('nextLink')
page.click()
except Exception as e:
return False
return True # 在登录页进行登录
def login(self):
# 莫名其妙有时根据ID获取不到邮箱填写框,出错时根据xpath再找一次
try:
email = self.driver.find_element_by_id('email')
except NoSuchElementException as e:
email = self.driver.find_element_by_class_name('ipt')
# email = self.driver.find_element_by_xpath('/html/body/div[4]/div/form/div/p[1]/input')
passwd = self.driver.find_element_by_id('password')
code = self.driver.find_element_by_id('myCode')
code_password = self.get_code1()
email.clear()
# 怕填写太快,添加延时
for i in self.login_email:
email.send_keys(i)
time.sleep(random.random())
for i in self.login_password:
passwd.send_keys(i)
time.sleep(random.random())
for i in code_password:
code.send_keys(i)
time.sleep(random.random())
time.sleep(5)
# 找到登录按钮点击登录
login = self.driver.find_element_by_xpath('/html/body/div[4]/div/form/div/p[5]/a/span')
login.click()
time.sleep(2)
# 如果捕捉到“验证码错误”,则重新进行填写登录
try:
code_err = self.driver.find_element_by_id('myCode_error')
#重新填写
self.login()
except:
time.sleep(2)
self.driver.get(self.url)
return True # 如果flag为0则全量下载,如果flag为1则只下载最新的一个文件
def run(self, flag=0):
self.driver.get(self.url)
if self.login():
while True:
self.get_file(flag=flag)
time.sleep(2)
if flag == 1:
break
result = self.get_next_page() if not result:
break
self.driver.close()
self.driver.quit() if __name__ == '__main__':
if len(sys.argv) != 2:
print('请添加参数 init:初始化规则库 update:更新规则库')
sys.exit()
get_cnvd_rule = DownloadCnvd()
if sys.argv[1] == 'init':
get_cnvd_rule.run()
elif sys.argv[1] == 'update':
get_cnvd_rule.run(1)
else:
print('请添加参数 init:初始化规则库 update:更新规则库')
#get_cnvd_rule = DownloadCnvd()
#get_cnvd_rule.run()

无界面Linux系统和Windows系统使用selenium爬取CNVD数据的更多相关文章

  1. linux系统和Windows系统共存

    最近接触了linux系统,因为对linux系统一直存在一种敬畏之心,所以决定研究研究 那么今天我在这里呢是要和大家分享一下在Windows存在的情况下安装双系统linux 那么第一步呢,就是斤BIOS ...

  2. 关于Linux系统和Windows系统中文件夹的命名规范

    Windows系统中. 1.在创建文件夹的时候不能以"."开头(但是文件以多个点开头并且还有其他合法字符的话就是合法的) 但是在windows系统中确实见过以一个点".& ...

  3. 对比Linux系统和Windows系统哪个更好

    最近半年来,我一直在读一本叫做<Linux就该这么学>的Linux教材,确实让我进步的很快,也慢慢的让Linux系统走入了我的知识认知中,那么学习前我们来对比下Windows和Linux的 ...

  4. 【转载】DOS 系统和 Windows 系统有什么关系?为什么windows系统下可以执行dos命令?

    作者:bombless 因为不同的系统都叫 Windows ,这些系统在界面上也有一定连续性并且因此可能造成误解,所以有必要稍微梳理一下几个不同的 Windows 系统.首先是 DOS 上的一个图形界 ...

  5. 六、利用frp穿透连接内网的linx系统和windows系统

    服务端的配置 # frps.ini [common] bind_port = 7000 说明:防火墙放行该端口 启动:./frps -c ./frps.ini 后台启动:nohup ./frps -c ...

  6. 实现虚拟机上面的linux系统和windows主机的通信

    一:配置静态ip 1:使用startx命名切换到图形化用户界面: 2:在“开始”——“系统设置”——“网络”——eth0 将通过dchp自动获取ip改为静态绑定ip ip地址:填入你要给的ip,需要与 ...

  7. vsftpd安装和使用 Linux系统和window系统

    vsftpd 安装(Linux)一.安装系统环境 centos 6.9 64位二.vsftpd版本 vsftpd-2.2.2-24.el6.x86_64三.安装步骤1.安装 执行 yum -y ins ...

  8. git安装和使用 linux系统和window系统

    一.git简介 git是一款免费.开放源代码的分布式版本控制系统特点: git是一个开源的分布式版本控制系统,可以有效, 高速的处理从很小到非常大的项目版本管理 二.git安装 Linux:下载.安装 ...

  9. samba服务设置,Linux系统和Windows文件共享

    samba是一个工具套件,在Unix上实现SMB(Server Message Block)协议,或者称之为NETBIOS/LanManager协议.SMB协议通常是被windows系列用来实现磁盘和 ...

  10. android系统和ios系统是如何实现推送的,ios为什么没有后台推送

    ios系统为什么没有后台推送? iOS 为了真正地为用户体验负责,不允许应用在后台活动.有了这个限制,但是对于终端设备,应用又是有必要“通知”到达用户的,随时与用户主动沟通起来的(典型的如聊天应用). ...

随机推荐

  1. Networking && Internet 计网学习笔记一

    Networking && Internet 计网学习笔记一 参考书籍: James F. Kurose, Keith W. Ross. 计算机网络-自顶向下方法 (7th). 机械工 ...

  2. 推荐一款.Net Core开发的后台管理系统YiShaAdmin

    若依(RuoYi)是码云上一款精美的开源快速开发平台,作者毫无保留给个人及企业免费使用.RuoYi目前有三个版本:普通版本(RuoYi).前后端分离版本(RuoYi-Vue).微服务版本(RuoYi- ...

  3. [AHOI2002]黑白瓷砖

    \(\text{Solution}\) 根据 \(Polya\) 定理推算 记总砖数为 \(m = \frac{n(n+1)}2\) 考虑旋转,不动点数均为为 \(2^{\frac{m+2}3}\) ...

  4. JZOJ 5350. 【NOIP2017提高A组模拟9.7】陶陶摘苹果

    题目 分析 很神奇的事情又发生了!! 很容易想到设 \(f_{i,j}\) 表示考虑前 \(i\) 个区间,已选 \(j\) 个区间且必选第 \(i\) 时能覆盖到的最多苹果数 转移 \(O(n)\) ...

  5. PHP的25种框架

    本篇文章给大家分享的内容是25种PHP框架 -有着一定的参考价值,有需要的朋友可以参考一下. 世界流行框架汇总 在项目开发中,一些架构和代码都是重复的,为了避免重复劳动,于是各种各样的框架诞生了. 在 ...

  6. 初学 Canvas

    画布的概念 Canvas(画布)可以用于动画.游戏画面.数据可视化.图片编辑以及实时视频处理等方面.画布在 HTML5 中是通过canvas标签来表现,通过 JavaScript 提供的画布 API, ...

  7. QFileDialog实现同时选择文件和文件夹,确认取消按钮英文问题解决方法

    如下图所示,需求是同时能够选择文件或者文件夹,但是QFileDialog文件窗口类要么只能选文件,要么只能选文件夹,无法同时去选择文件和文件夹: 要实现这样的需求,封装了一个类,实现同时选择文件和文件 ...

  8. 数据转换工具DBT介绍及实操

    一.什么是DBT dbt (data build tool)是一款流行的开源数据转换工具,能够通过 SQL 实现数据转化,将命令转化为表或者视图,提升数据分析师的工作效率.dbt 主要功能在于转换数据 ...

  9. 微信小程序分享百度网盘文件的实现思路

    需求: 在小程序中点击按钮,获取百度网盘文件的下载地址. 实现思路: 1.网盘文件的下载地址,使用官方API只能自己下载,别人通过dlink无法下载,所以采用网页端生成接口. 好处是可以自定义提取码, ...

  10. python去重的几种方法

    from collections import OrderedDict list1 = [1,5,2,1,10] print(list(set(list1))) #[1, 2, 10, 5] 这种方式 ...