(上)python3 selenium3 从框架实现代码学习selenium让你事半功倍

本文感谢以下文档或说明提供的参考。
Selenium-Python中文文档
Selenium Documentation
Webdriver 参考

如有错误欢迎在评论区指出,作者将即时更改。

环境说明

  • 操作系统:Windows7 SP1 64
  • python 版本:3.7.7
  • 浏览器:谷歌浏览器
  • 浏览器版本: 80.0.3987 (64 位)
  • 谷歌浏览器驱动:驱动版本需要对应浏览器版本,不同的浏览器使用对应不同版本的驱动,点击下载
  • 如果是使用火狐浏览器,查看火狐浏览器版本,点击 GitHub火狐驱动下载地址 下载(英文不好的同学右键一键翻译即可,每个版本都有对应浏览器版本的使用说明,看清楚下载即可)

简介

Selenium是一个涵盖了一系列工具和库的总体项目,这些工具和库支持Web浏览器的自动化。并且在执行自动化时,所进行的操作会像真实用户操作一样。

Selenium有3个版本,分别是 Selenium 1.0、Selenium2.0、Selenium3.0;

Selenium 1.0 主要是调用JS注入到浏览器;最开始Selenium的作者Jason Huggins开发了JavaScriptTestRunner作为测试工具,当时向多位同事进行了展示(这个作者也是个很有趣的灵魂)。从这个测试工具的名字上可以看出,是基于JavaScript进行的测试。这个工具也就是Selenium的“前身”。

Selenium 2.0 基于 WebDriver 提供的API,进行浏览器的元素操作。WebDriver 是一个测试框架也可以说是一个集成的API接口库。

Selenium 3.0 基于 Selenium 2.0 进行扩展,基本差别不大;本文将以Selenium 3.0 版本进行技术说明。

在官方介绍中介绍了有关支持浏览器的说明:“通过WebDriver,Selenium支持市场上所有主流浏览器,例如Chrom(ium),Firefox,Internet Explorer,Opera和Safari。

简单开始

安装好环境后,简单的使用selenium让浏览器打开CSDN官网。
在环境配置时需要注意:必须把驱动给配置到系统环境,或者丢到你python的根目录下。

首先引入 webdriver :

from selenium.webdriver import Chrome

当然也可以:

from selenium import webdriver

引入方式因人而异,之后使用不同的方法新建不同的实例。

from selenium.webdriver import Chrome
driver = Chrome()

或者

from selenium import webdriver
driver = webdriver.Chrome()

一般性的python语法将不会在下文赘述。
之前所提到,需要把驱动配置到系统环境之中,但不外乎由于其它原因导致的不能驱动路径不能加入到系统环境中,在这里提供一个解决方法:

from selenium import webdriver
driver = webdriver.Chrome(executable_path=r'F:\python\dr\chromedriver_win32\chromedriver.exe')

这里使用 executable_path 指定驱动地址,这个地址是我驱动所存放的位置。当然这个位置可以根据自己需求制定,并且以更加灵活;本文为了更好说明,所以使用了绝对路径传入。

火狐浏览器:

from selenium import webdriverdriver = webdriver.Firefox()
driver.get("http://www.csdn.net")

谷歌浏览器:

from selenium import webdriverdriver = webdriver.Chrome()
driver.get("http://www.csdn.net")

火狐浏览器与谷歌浏览器只有实例化方法不同,其它的操作方法均一致。

在代码最开头引入 webdriver ,在代码中实例化浏览器对象后,使用get方法请求网址,打开所需要的网址。

实现剖析

查看 webdriver.py 实现(from selenium import webdriver):

import warningsfrom selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver
from .remote_connection import ChromeRemoteConnection
from .service import Service
from .options import Optionsclass WebDriver(RemoteWebDriver):"""Controls the ChromeDriver and allows you to drive the browser.You will need to download the ChromeDriver executable fromhttp://chromedriver.storage.googleapis.com/index.html"""def __init__(self, executable_path="chromedriver", port=0,options=None, service_args=None,desired_capabilities=None, service_log_path=None,chrome_options=None, keep_alive=True):"""Creates a new instance of the chrome driver.Starts the service and then creates new instance of chrome driver.:Args:- executable_path - path to the executable. If the default is used it assumes the executable is in the $PATH- port - port you would like the service to run, if left as 0, a free port will be found.- options - this takes an instance of ChromeOptions- service_args - List of args to pass to the driver service- desired_capabilities - Dictionary object with non-browser specificcapabilities only, such as "proxy" or "loggingPref".- service_log_path - Where to log information from the driver.- chrome_options - Deprecated argument for options- keep_alive - Whether to configure ChromeRemoteConnection to use HTTP keep-alive."""if chrome_options:warnings.warn('use options instead of chrome_options',DeprecationWarning, stacklevel=2)options = chrome_optionsif options is None:# desired_capabilities stays as passed inif desired_capabilities is None:desired_capabilities = self.create_options().to_capabilities()else:if desired_capabilities is None:desired_capabilities = options.to_capabilities()else:desired_capabilities.update(options.to_capabilities())self.service = Service(executable_path,port=port,service_args=service_args,log_path=service_log_path)self.service.start()try:RemoteWebDriver.__init__(self,command_executor=ChromeRemoteConnection(remote_server_addr=self.service.service_url,keep_alive=keep_alive),desired_capabilities=desired_capabilities)except Exception:self.quit()raiseself._is_remote = Falsedef launch_app(self, id):"""Launches Chrome app specified by id."""return self.execute("launchApp", {'id': id})def get_network_conditions(self):return self.execute("getNetworkConditions")['value']def set_network_conditions(self, **network_conditions):self.execute("setNetworkConditions", {'network_conditions': network_conditions})def execute_cdp_cmd(self, cmd, cmd_args):return self.execute("executeCdpCommand", {'cmd': cmd, 'params': cmd_args})['value']def quit(self):try:RemoteWebDriver.quit(self)except Exception:# We don't care about the message because something probably has gone wrongpassfinally:self.service.stop()def create_options(self):return Options()

从注释中表明这是 “创建chrome驱动程序的新实例,并且创建chrome驱动程序的实例”

在此只列出本篇文章使用到的参数:

  • executable_path:可执行文件的路径。如果使用默认值,则假定可执行文件位于PATH中;其中的PATH为系统环境根目录

在 selenium 实现自动化过程中,必要的一步是启动服务,查看 init初始化方法中,发现了以下代码:

self.service = Service(executable_path,port=port,service_args=service_args,log_path=service_log_path)
self.service.start()

以上代码实例化了Service类,并且传入相关参数,之后启动服务;在这里最主要的参数为 executable_path,也就是启动驱动。查看 Service 类(selenium.service):

from selenium.webdriver.common import serviceclass Service(service.Service):"""Object that manages the starting and stopping of the ChromeDriver"""def __init__(self, executable_path, port=0, service_args=None,log_path=None, env=None):"""Creates a new instance of the Service:Args:- executable_path : Path to the ChromeDriver- port : Port the service is running on- service_args : List of args to pass to the chromedriver service- log_path : Path for the chromedriver service to log to"""self.service_args = service_args or []if log_path:self.service_args.append('--log-path=%s' % log_path)service.Service.__init__(self, executable_path, port=port, env=env,start_error_message="Please see https://sites.google.com/a/chromium.org/chromedriver/home")def command_line_args(self):return ["--port=%d" % self.port] + self.service_args

查看基类 start 方法实现(由于基类过长不全部展出,基类在selenium.webdriver.common import service 中):

def start(self):"""Starts the Service.:Exceptions:- WebDriverException : Raised either when it can't start the serviceor when it can't connect to the service"""try:cmd = [self.path]cmd.extend(self.command_line_args())self.process = subprocess.Popen(cmd, env=self.env,close_fds=platform.system() != 'Windows',stdout=self.log_file,stderr=self.log_file,stdin=PIPE)except TypeError:raiseexcept OSError as err:if err.errno == errno.ENOENT:raise WebDriverException("'%s' executable needs to be in PATH. %s" % (os.path.basename(self.path), self.start_error_message))elif err.errno == errno.EACCES:raise WebDriverException("'%s' executable may have wrong permissions. %s" % (os.path.basename(self.path), self.start_error_message))else:raiseexcept Exception as e:raise WebDriverException("The executable %s needs to be available in the path. %s\n%s" %(os.path.basename(self.path), self.start_error_message, str(e)))count = 0while True:self.assert_process_still_running()if self.is_connectable():breakcount += 1time.sleep(1)if count == 30:raise WebDriverException("Can not connect to the Service %s" % self.path)

其中发现:

try:cmd = [self.path]cmd.extend(self.command_line_args())self.process = subprocess.Popen(cmd, env=self.env,close_fds=platform.system() != 'Windows',stdout=self.log_file,stderr=self.log_file,stdin=PIPE)
except TypeError:raiseexcept OSError as err:if err.errno == errno.ENOENT:raise WebDriverException("'%s' executable needs to be in PATH. %s" % (os.path.basename(self.path), self.start_error_message))elif err.errno == errno.EACCES:raise WebDriverException("'%s' executable may have wrong permissions. %s" % (os.path.basename(self.path), self.start_error_message))else:raiseexcept Exception as e:raise WebDriverException("The executable %s needs to be available in the path. %s\n%s" %(os.path.basename(self.path), self.start_error_message, str(e)))count = 0while True:self.assert_process_still_running()if self.is_connectable():breakcount += 1time.sleep(1)if count == 30:raise WebDriverException("Can not connect to the Service %s" % self.path)

启动子进程开启驱动。在出现异常时接收抛出异常并且报错。开启驱动打开浏览器。

在异常抛出检测到此已知道了selenium如何启动服务。接下来查看get请求网址的实现流程。
查看webdriver基类(selenium.webdriver.remote.webdriver),找到get方法:

def get(self, url):"""Loads a web page in the current browser session."""self.execute(Command.GET, {'url': url})def execute(self, driver_command, params=None):"""Sends a command to be executed by a command.CommandExecutor.:Args:- driver_command: The name of the command to execute as a string.- params: A dictionary of named parameters to send with the command.:Returns:The command's JSON response loaded into a dictionary object."""if self.session_id is not None:if not params:params = {'sessionId': self.session_id}elif 'sessionId' not in params:params['sessionId'] = self.session_idparams = self._wrap_value(params)response = self.command_executor.execute(driver_command, params)if response:self.error_handler.check_response(response)response['value'] = self._unwrap_value(response.get('value', None))return response# If the server doesn't send a response, assume the command was# a successreturn {'success': 0, 'value': None, 'sessionId': self.session_id}

通过get方法得知,调用了 execute 方法,传入了 Command.GET 与 url。
查看Command.GET的类Command(selenium.webdriver.remote.command)得知,Command为标准WebDriver命令的常量;找到GET常量:

GET = "get"

从文件上,应该是执行命令方式的类文件。
首先整理一下流程:

  • 启动服务→调用get方法

其中get方法具体流程:

  • get方法调用execute方法,传入参数为 Command.GET与url,查看Command的值是标准常量。 在execute方法中,

其中 execute 的实现为:

def execute(self, driver_command, params=None):"""Sends a command to be executed by a command.CommandExecutor.:Args:- driver_command: The name of the command to execute as a string.- params: A dictionary of named parameters to send with the command.:Returns:The command's JSON response loaded into a dictionary object."""if self.session_id is not None:if not params:params = {'sessionId': self.session_id}elif 'sessionId' not in params:params['sessionId'] = self.session_idparams = self._wrap_value(params)response = self.command_executor.execute(driver_command, params)if response:self.error_handler.check_response(response)response['value'] = self._unwrap_value(response.get('value', None))return response# If the server doesn't send a response, assume the command was# a successreturn {'success': 0, 'value': None, 'sessionId': self.session_id}

其中核心代码为:

params = self._wrap_value(params)
response = self.command_executor.execute(driver_command, params)
if response:self.error_handler.check_response(response)response['value'] = self._unwrap_value(response.get('value', None))return response

主要查看:

self.command_executor.execute(driver_command, params)

其中 command_executor 为初始化后实例,查看派生类 webdriver(selenium import webdriver) command_executor 的实例化为:

RemoteWebDriver.__init__(self,command_executor=ChromeRemoteConnection(remote_server_addr=self.service.service_url,keep_alive=keep_alive),desired_capabilities=desired_capabilities)

查看 ChromeRemoteConnection 类(selenium import remote_connection):

from selenium.webdriver.remote.remote_connection import RemoteConnectionclass ChromeRemoteConnection(RemoteConnection):def __init__(self, remote_server_addr, keep_alive=True):RemoteConnection.__init__(self, remote_server_addr, keep_alive)self._commands["launchApp"] = ('POST', '/session/$sessionId/chromium/launch_app')self._commands["setNetworkConditions"] = ('POST', '/session/$sessionId/chromium/network_conditions')self._commands["getNetworkConditions"] = ('GET', '/session/$sessionId/chromium/network_conditions')self._commands['executeCdpCommand'] = ('POST', '/session/$sessionId/goog/cdp/execute')

得知调用的是基类初始化方法,查看得知 execute 方法实现为:

def execute(self, command, params):"""Send a command to the remote server.Any path subtitutions required for the URL mapped to the command should beincluded in the command parameters.:Args:- command - A string specifying the command to execute.- params - A dictionary of named parameters to send with the command asits JSON payload."""command_info = self._commands[command]assert command_info is not None, 'Unrecognised command %s' % commandpath = string.Template(command_info[1]).substitute(params)if hasattr(self, 'w3c') and self.w3c and isinstance(params, dict) and 'sessionId' in params:del params['sessionId']data = utils.dump_json(params)url = '%s%s' % (self._url, path)return self._request(command_info[0], url, body=data)def _request(self, method, url, body=None):"""Send an HTTP request to the remote server.:Args:- method - A string for the HTTP method to send the request with.- url - A string for the URL to send the request to.- body - A string for request body. Ignored unless method is POST or PUT.:Returns:A dictionary with the server's parsed JSON response."""LOGGER.debug('%s %s %s' % (method, url, body))parsed_url = parse.urlparse(url)headers = self.get_remote_connection_headers(parsed_url, self.keep_alive)resp = Noneif body and method != 'POST' and method != 'PUT':body = Noneif self.keep_alive:resp = self._conn.request(method, url, body=body, headers=headers)statuscode = resp.statuselse:http = urllib3.PoolManager(timeout=self._timeout)resp = http.request(method, url, body=body, headers=headers)statuscode = resp.statusif not hasattr(resp, 'getheader'):if hasattr(resp.headers, 'getheader'):resp.getheader = lambda x: resp.headers.getheader(x)elif hasattr(resp.headers, 'get'):resp.getheader = lambda x: resp.headers.get(x)data = resp.data.decode('UTF-8')try:if 300 <= statuscode < 304:return self._request('GET', resp.getheader('location'))if 399 < statuscode <= 500:return {'status': statuscode, 'value': data}content_type = []if resp.getheader('Content-Type') is not None:content_type = resp.getheader('Content-Type').split(';')if not any([x.startswith('image/png') for x in content_type]):try:data = utils.load_json(data.strip())except ValueError:if 199 < statuscode < 300:status = ErrorCode.SUCCESSelse:status = ErrorCode.UNKNOWN_ERRORreturn {'status': status, 'value': data.strip()}# Some of the drivers incorrectly return a response# with no 'value' field when they should return null.if 'value' not in data:data['value'] = Nonereturn dataelse:data = {'status': 0, 'value': data}return datafinally:LOGGER.debug("Finished Request")resp.close()

从以上实现得知,execute 为向远程服务器发送请求;execute中调用的_request方法为发送http请求并且返回相关结果,请求结果通过浏览器进行响应。

官方说明中说明了请求原理:

At its minimum, WebDriver talks to a browser through a driver.
Communication is two way: WebDriver passes commands to the browser through the driver, and receives information back via the same route.
在这里插入图片描述
The driver is specific to the browser, such as ChromeDriver for Google’s Chrome/Chromium, GeckoDriver for Mozilla’s Firefox, etc. Thedriver runs on the same system as the browser. This may, or may not be, the same system where the tests themselves are executing.
This simple example above is direct communication. Communication to the browser may also be remote communication through Selenium Server or RemoteWebDriver. RemoteWebDriver runs on the same system as the driver and the browser.

言而总之我们通过webdriver与浏览器进行对话,从而浏览器进行响应。

通过以上实例得知,使用 execute 向远程服务器发送请求会通过 webdriver 与浏览器交互,且发送已定义的命令常量可获得一些相关信息。

由于在代码中我们实例的是 webdriver 实例,去 webdriver基类(selenium.webdriver.remote.webdriver)中查询相关信息,是否有相关函数可以获取信息。发现以下函数:

def title(self):"""Returns the title of the current page.:Usage:title = driver.title"""resp = self.execute(Command.GET_TITLE)return resp['value'] if resp['value'] is not None else ""
@property
def current_url(self):"""Gets the URL of the current page.:Usage:driver.current_url"""return self.execute(Command.GET_CURRENT_URL)['value']
@property
def page_source(self):"""Gets the source of the current page.:Usage:driver.page_source"""return self.execute(Command.GET_PAGE_SOURCE)['value']

以上并没有列全,我们简单的尝试以上函数的使用方法,使用方法在函数中已经说明。尝试获取 title(标题)、current_url(当前url)、page_source(网页源代码):

from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.csdn.net")
print(driver.title)
print(driver.current_url)
print('作者博客:https://blog.csdn.net/A757291228')
#支持原创,转载请贴上原文链接
# print(driver.page_source)

结果成功获取到网页标题以及当前网址:
在这里插入图片描述
试试 page_source:

from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.csdn.net")
print(driver.title)
print(driver.current_url)
print('作者博客:https://blog.csdn.net/A757291228')
#支持原创,转载请贴上链接
print(driver.page_source)

成功获取:
在这里插入图片描述
原创不易,看到这里点个赞支持一下呗!谢谢

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/288165.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET 7 中的 HostApplicationBuilder

.NET 7 Preview 3 引入的 HostApplicationBuilderIntro在 .NET 6 中&#xff0c;ASP.NET Core 引入了 Minimal API&#xff0c;对于简单的应用使用 Minimal API 我们可以使用非常精简的代码来实现我们的 API&#xff0c;在 .NET 7 Preview 3 中&#xff0c;引入了一个 HostAppl…

SQL Server 2008 R2 Developer Edition图文安装教程

本文主要以截图的方式,详细说明SQL Server 2008 R2 Developer Edition的安装过程。 1、双击安装包中的setup.exe,如下图,点击“安装”→“全新安装或现有安装添加功能”。 2、点击“确定”。 3、点击“下一步”。

新款ATM恶意软件Alice 可对抗动态分析 但目前需要物理接触主机

趋势科技&#xff08;Trend Micro&#xff09;安全公司的研究人员警告称&#xff0c;新发现的恶意软件家族主要针对ATM机&#xff08;自动取款机&#xff09;&#xff0c;唯一目的就是要掏空ATM机保险箱里的现金。 alice软件是什么 这款恶意软件被称为“Alice”&#xff0c;是迄…

(下)python3 selenium3 从框架实现代码学习selenium让你事半功倍

上一篇博文简要 在上一篇博文中已得知&#xff1a;使用 execute 向远程服务器发送请求会通过 webdriver 与浏览器交互&#xff0c;且发送已定义的命令常量可获得一些相关信息。 其中 execute 方法实现已经在上一篇博文中有实现说明。并且在我们已经知道 webdriver基类&#x…

【空间数据库技术】ArcSDE 10.1安装配置与企业级地理空间数据库的建立及连接

1、工具: (1)ArcGIS Desktop 10.1 (2)SQL Server 2008 R2 (3)ArcSDE 10.1 2、安装过程 (1)ArcGIS Desktop 10.1的安装 请参照:ArcGIS 10.2 Desktop完全破解图文安装教程 (2)SQL Server 2008 R2的安装 请参照:SQL Server 2008 R2 Developer Edition图文安装教…

点对点 客户端-服务器 聊天程序

服务器&#xff0c;客户端都是父进程、子进程分别负责发送、接收字符串。 另外使用了信号函数来发送和接收处理信号&#xff0c;比如当子进程结束时&#xff0c;传递一个信号给父进程&#xff0c;然后父进程会执行信号处理函数。 服务器端&#xff1a; 1 #include<stdio.h&g…

C# 使用压缩流和 Brotli

如前所述&#xff0c;流的一个特性是可以将它们链接起来。为了压缩流&#xff0c;只需要创建 DeflateStream&#xff0c;并给构造函数传递另一个流(在这个例子中&#xff0c;是写入文件的outputStream)&#xff0c;使用 CompressionMode. Compress 表示压缩。使用 Write方法或其…

高考610考哪个计算机学校,2019年高考成绩610分_615分左右能报考上什么学校 文科理科大学名单推荐...

一眨眼&#xff0c;高考已经结束一段时间了&#xff1b;早晨猛地一睁眼&#xff0c;还在抱怨妈妈怎么不叫你起床&#xff0c;才突然发现今天你已经不用去学校了,这场全国性的考试高考已经结束了&#xff1b;高考这个城门攻破之后&#xff0c;还有大把壁垒再等你去攻克&#xff…

Power的力量

ZD至顶网服务器频道 08月26日 新闻消息&#xff08;文/董培欣&#xff09;&#xff1a;谈到企业级服务器市场&#xff0c;人们首先想到的会是x86 E5、E7系列的CPU产品&#xff0c;IBM在企业级市场推出的Power Systems服务器产品很少会被用户了解。可是在今年春天举行的OpenPOWE…

C#语法糖系列 —— 第三篇:聊聊闭包的底层玩法

有朋友好奇为什么将 闭包 归于语法糖&#xff0c;这里简单声明下&#xff0c;C# 中的所有闭包最终都会归结于 类 和 方法&#xff0c;为什么这么说&#xff0c;因为 C# 的基因就已经决定了&#xff0c;如果大家了解 CLR 的话应该知道&#xff0c; C#中的类最终都会用 MethodTab…

空间数据库Spatial Tools的使用

工具下载:http://www.sharpgis.net/page/SQL-Server-2008-Spatial-Tools 该工具为绿色版,点击即可使用。 1、导入Shapefile数据 双击“Shape2Sql.exe”,打开界面如下: 2、查询空间数据 双击打开“SqlSpatial.exe”

自定义View 进度条

1.在values下面新建一个attrs.xml&#xff0c;现在里面定义我们的自定义属性&#xff0c; <?xml version"1.0" encoding"utf-8"?> <resources><declare-styleable name"RoundProgressBar"><attr name"roundColor&qu…

python图形绘制库turtle中文开发文档及示例大全【最详细、连结果图都有,gif格式的!】

前言 本文参考&#xff1a;Python库官方文档 本文例子摘抄自Python库官方文档&#xff0c;为了方便讲解&#xff0c;个人进行了修改&#xff0c;并且相关函数说明不完全参照文档&#xff0c;在结果处贴出了执行结果&#xff0c;不方便用jpg等图片作为展示的用了gif格式图片进行…

oracle 事务_从Oracle到PG-PostgreSQL的MVCC机制简介

作者&#xff1a;甘植恳-AkenPostgreSQL和Oracle、MySQL等RDBMS一样&#xff0c;都有自己的并发控制机制。而并发控制的目的是为了在多个事务同时运行时保持事务ACID属性。MVCC即Multi-version concurrence control首字母缩写&#xff0c;MVCC会为每个数据更改操作创建数据块或…

【Microstation】不能从对话框中装载/创建类型为 ‘HTML‘,id =41510001 的对话框条目,该对话框为: “文本编辑器 - 字处理器“,GCSDIALOG 已装载。

在Win7上安装MicroStation V8i简体中文版,在添加文字图层的时候,点击出现提示“不能从对话框中装载/创建类型为 HTML,id =41510001 的对话框条目,该对话框为: "文本编辑器 - 字处理器",GCSDIALOG 已装载。”,问题出在Win7对该软件的兼容性上。 MS软件提供了三种…

fastdfs 一个group内实现按照不同的项目,指定路径存储.

为什么80%的码农都做不了架构师&#xff1f;>>> 环境介绍: 1: 公司目前有5个项目 A B C D E 日后可能会有所增加. 2: 使用fastdfs存储这5各项目的文件,要求各各项目的文件分开存储,也就是每个项目的文件存储到一个固定的位置. 3: 三台机器ip地址分配如下 tracker…

一个WPF开发的打印对话框-PrintDialogX

今天五月一号&#xff0c;大家玩的开心哦。1. 介绍今天介绍一个WPF开发的打印对话框开源项目-PrintDialogX[1]&#xff0c;该开源项目由《WPF开源项目&#xff1a;AIStudio.Wpf.AClient》[2]作者推荐。欢迎使用 PrintDialogX, 这是一个开源项目。免费用于商业用途。用于 C# 的自…

这一新的可视化方法教你优雅地探索相关性

一个古老的诅咒一直萦绕着数据分析&#xff1a;我们用来改进模型的变量越多&#xff0c;那么我们需要的数据就会出现指数级的增长。不过&#xff0c;我们通过关注重要的变量就可以避免欠拟合以及降低收集大量数据的需求。减少输入变量的一种方法是鉴别其对输出变量的影响。变量…

【新手宝典】一篇博文带萌新建站并了解建站体系流程和对萌新友好的便捷方式,这篇博文很有可能是你的启蒙文

前言 本片博文主要面向于还没接触过web开发的萌新&#xff0c;以及想知道整体流程并且完成建站的萌新&#xff1b;如果你是个大佬&#xff0c;就没必要看下去了。 本篇博文没有难啃的骨头&#xff0c;请各位萌新放心食用。 本篇博文采用通俗易懂的方式讲解&#xff0c;轻松并…

MicroStation V8i简体中文版中文字体乱码解决办法

Bentley (奔特力)是一家软件研发公司,其核心业务是满足负责建造和管理全球基础设施,包括公路、桥梁、机场、摩天大楼、工业厂房和电厂以及公用事业网络等领域专业人士的需求。Bentley 在基础设施资产的整个生命周期内针对不同的职业,包括工程师、建筑师、规划师、承包商、…