7 selenium 模块

selenium 模块

一.简介

1.Python的一个第三方库,对外提供的接口可以操作浏览器,然后让浏览器完成自动化的操作。

2.自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器。

二.下载

1.需要先下载驱动

mac系统: 然后将解压后的chromedriver移动到/usr/local/bin目录下

windows系统:下载chromdriver.exe放到python安装路径的scripts目录

2.安装pip 包 

pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple selenium

注意:selenium3默认支持的webdriver是Firfox,而Firefox需要安装geckodriver 

 

三.selenium模块的使用

 

1.简单使用

from selenium import webdriver
from time import sleep# 后面是你的浏览器驱动位置,记得前面加r'','r'是防止字符转义的
driver = webdriver.Chrome()
# 用get打开百度页面
driver.get("http://www.baidu.com")
# 查找页面的“设置”选项,并进行点击
driver.find_elements_by_link_text('设置')[0].click()
sleep(2)
# # 打开设置后找到“搜索设置”选项,设置为每页显示50条
driver.find_elements_by_link_text('搜索设置')[0].click()
sleep(2)# 选中每页显示50条
m = driver.find_element_by_id('nr')
sleep(2)
m.find_element_by_xpath('//*[@id="nr"]/option[3]').click()
m.find_element_by_xpath('.//option[3]').click()
sleep(2)# 点击保存设置
driver.find_elements_by_class_name("prefpanelgo")[0].click()
sleep(2)# 处理弹出的警告页面   确定accept() 和 取消dismiss()
driver.switch_to.alert().accept()
sleep(2)
# 找到百度的输入框,并输入 美女
driver.find_element_by_id('kw').send_keys('美女')
sleep(2)
# 点击搜索按钮
driver.find_element_by_id('su').click()
sleep(2)
# 在打开的页面中找到“Selenium - 开源中国社区”,并打开这个页面
driver.find_elements_by_link_text('美女_百度图片')[0].click()
sleep(3)# 关闭浏览器
driver.quit()

Selenium支持非常多的浏览器,如Chrome、Firefox、Edge等,还有Android、BlackBerry等手机端的浏览器。另外,也支持无界面浏览器PhantomJS

from selenium import webdriverbrowser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.Edge()
browser = webdriver.PhantomJS()
browser = webdriver.Safari()

2.元素定位

webdriver提供了大致8种,元素定位的方法:

1.   id   =====>   find_element_by_id()2. name=====>find_element_by_name()3.class name==>find_element_by_calss_name()4.tag name====>find_element_by_tag_name()5.link text=====>find_element_by_link_text()6.partial link text ==>find_element_by_partial_link_text()7.xpath========> find_element_by_xpath()8.css selector ===> find_element_by_css_selector()

注意:

1. find_element_by_xxx     找到第一个符合条件的标签

2.find_elements_by_xxx  所有符合条件标签

3. find_element(查询方式,值)   

  find_element_by_id(id)  ==> find_element(By.ID,id)

 3.节点交互

1.  tag.send_keys("内容")      # 输入内容

2. tag .clear()    # 清空输入内容

3. tag.click()    # 点击

from selenium import webdriver
import time# 节点交互
browser=webdriver.Chrome()  # 实例化一个浏览器对象

browser.get("https://www.taobao.com")  # 让浏览器 去访问淘宝

input = browser.find_element_by_id("q") # 找到 输入搜索框

input.send_keys("python")  # 在输入框中输入内容

time.sleep(1)input.clear()  # 将上次输入的内容清空

input.send_keys("鞋子")search =browser.find_element_by_xpath('//*[@id="J_TSearchForm"]/div[1]/button') # 找到搜索按钮

search.click()  # 点击搜索按钮

time.sleep(2)

 4.动作链

from selenium import webdriver
from selenium.webdriver import ActionChains
import timebrowser =webdriver.Chrome()# 获取一个浏览器对象
browser.get("http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable")  # 让该浏览器去访问该地址

browser.switch_to_frame('iframeResult')  # 找到id 为  'iframeResult'     iframe 中嵌套着另一个html 文档
source=browser.find_element_by_css_selector('#draggable')
target=browser.find_element_by_css_selector('#droppable')action=ActionChains(browser)
# action.drag_and_drop(source,target) # 拖到目标
action.click_and_hold(source).perform() # 点击不放
time.sleep(1)
action.move_to_element(target).perform()  # 移动到目标
time.sleep(1)
action.move_by_offset(xoffset=50,yoffset=50).perform()  # 在右移20 ,下移10
time.sleep(3)
action.release()  # 解除动作

browser.close()

5.执行js代码

用途:爬取动态页面等,下拉才不断显示新数据的动态页面

from selenium import webdriver
import time
browser =webdriver.Chrome()
browser.get("https://www.jd.com/")
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')# 从上到下一直拉到浏览器底部

browser.execute_script("alert('123')")browser.close() # 关闭浏览器

6.获取节点信息

 

from selenium import webdriver
from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素

browser=webdriver.Chrome()browser.get('https://www.amazon.cn/')wait=WebDriverWait(browser,10)
wait.until(EC.presence_of_element_located((By.ID,'cc-lm-tcgShowImgContainer')))tag=browser.find_element(By.CSS_SELECTOR,'#cc-lm-tcgShowImgContainer img')#获取标签属性,
print(tag.get_attribute('src'))
#获取标签ID,位置,名称,大小(了解)
print(tag.id)
print(tag.location)
print(tag.tag_name)
print(tag.size)browser.close()

7.延时等待

在Selenium中,get()方法会在网页框架加载结束后结束执行,此时如果获取page_source,可能并不是浏览器完全加载完成的页面,如果某些页面有额外的Ajax请求,我们在网页源代码中也不一定能成功获取到。所以,这里需要延时等待一定时间,确保节点已经加载出来。这里等待的方式有两种:一种是隐式等待,一种是显式等待。

隐式等待:

当使用隐式等待执行测试的时候,如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常。换句话说,当查找节点而节点并没有立即出现的时候,隐式等待将等待一段时间再查找DOM,默认的时间是0。示例如下:

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #键盘按键操作
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素

browser=webdriver.Chrome()#隐式等待:在查找所有元素时,如果尚未被加载,则等10秒
browser.implicitly_wait(10)browser.get('https://www.baidu.com')
input_tag=browser.find_element_by_id('kw')
input_tag.send_keys('美女')
input_tag.send_keys(Keys.ENTER)contents=browser.find_element_by_id('content_left') #没有等待环节而直接查找,找不到则会报错
print(contents)browser.close()

显示等待:

隐式等待的效果其实并没有那么好,因为我们只规定了一个固定时间,而页面的加载时间会受到网络条件的影响。这里还有一种更合适的显式等待方法,它指定要查找的节点,然后指定一个最长等待时间。如果在规定时间内加载出来了这个节点,就返回查找的节点;如果到了规定时间依然没有加载出该节点,则抛出超时异常。

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #键盘按键操作
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素

browser=webdriver.Chrome()
browser.get('https://www.baidu.com')input_tag=browser.find_element_by_id('kw')
input_tag.send_keys('美女')
input_tag.send_keys(Keys.ENTER)#显式等待:显式地等待某个元素被加载
wait=WebDriverWait(browser,10)
wait.until(EC.presence_of_element_located((By.ID,'content_left')))contents=browser.find_element(By.CSS_SELECTOR,'#content_left')
print(contents)browser.close()

8.cookies

# 对Cookies进行操作,例如获取、添加、删除Cookies等。from selenium import webdriverbrowser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies())
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())

9.异常处理

from selenium import webdriver
from selenium.common.exceptions import TimeoutException,NoSuchElementException,NoSuchFrameExceptiontry:browser=webdriver.Chrome()browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')browser.switch_to.frame('iframssseResult')except TimeoutException as e:print(e)
except NoSuchFrameException as e:print(e)
finally:browser.close()

四 phantomJs

PhantomJS是一款无界面的浏览器,其自动化操作流程和上述操作谷歌浏览器是一致的。

能够展示自动化操作流程,PhantomJS提供了一个截屏的功能,使用save_screenshot函数实现。

from selenium import webdriver
import time# phantomjs路径
path = r'PhantomJS驱动路径'
browser = webdriver.PhantomJS(path)# 打开百度
url = 'http://www.baidu.com/'
browser.get(url)time.sleep(3)browser.save_screenshot(r'phantomjs\baidu.png')# 查找input输入框
my_input = browser.find_element_by_id('kw')
# 往框里面写文字
my_input.send_keys('美女')
time.sleep(3)
#截屏
browser.save_screenshot(r'phantomjs\meinv.png')# 查找搜索按钮
button = browser.find_elements_by_class_name('s_btn')[0]
button.click()time.sleep(3)browser.save_screenshot(r'phantomjs\show.png')time.sleep(3)browser.quit()

selenium+phantomjs 就是爬虫终极解决方案:

有些网站上的内容信息是通过动态加载js形成的,所以使用普通爬虫程序无法回去动态加载的js内容。

例如:豆瓣电影中的电影信息是通过下拉操作动态加载更多的电影信息。
需求 :尽可能多的爬取豆瓣网中的电影信息

 
from selenium import webdriver
from time import sleep
import timeif __name__ == '__main__':url = 'https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action='# 发起请求前,可以让url表示的页面动态加载出更多的数据path = r'D:\phantomjs\bin\phantomjs.exe'# 创建无界面的浏览器对象bro = webdriver.PhantomJS(path)# 发起url请求
    bro.get(url)time.sleep(3)# 截图bro.save_screenshot('1.png')# 执行js代码(让滚动条向下偏移n个像素(作用:动态加载了更多的电影信息))js = 'window.scrollTo(0,document.body.scrollHeight)'bro.execute_script(js)  # 该函数可以执行一组字符串形式的js代码time.sleep(2)bro.execute_script(js)  # 该函数可以执行一组字符串形式的js代码time.sleep(2)bro.save_screenshot('2.png') time.sleep(2) # 使用爬虫程序爬去当前url中的内容 html_source = bro.page_source # 该属性可以获取当前浏览器的当前页的源码(html) with open('./source.html', 'w', encoding='utf-8') as fp: fp.write(html_source) bro.quit()

 

破解滑动验证码:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait # 等待元素加载的
from selenium.webdriver.common.action_chains import ActionChains  #拖拽
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.common.by import By
from PIL import Image
import requests
import re
import random
from io import BytesIO
import timedef merge_image(image_file,location_list):"""拼接图片"""im = Image.open(image_file)im.save('code.jpg')new_im = Image.new('RGB',(260,116))# 把无序的图片 切成52张小图片im_list_upper = []im_list_down = []# print(location_list)for location in location_list:# print(location['y'])if location['y'] == -58: # 上半边im_list_upper.append(im.crop((abs(location['x']),58,abs(location['x'])+10,116)))if location['y'] == 0:  # 下半边im_list_down.append(im.crop((abs(location['x']),0,abs(location['x'])+10,58)))x_offset = 0for im in im_list_upper:new_im.paste(im,(x_offset,0))  # 把小图片放到 新的空白图片上x_offset += im.size[0]x_offset = 0for im in im_list_down:new_im.paste(im,(x_offset,58))x_offset += im.size[0]#new_im.show()return new_imdef get_image(driver,div_path):'''下载无序的图片  然后进行拼接 获得完整的图片:param driver::param div_path::return:'''background_images = driver.find_elements_by_xpath(div_path)location_list = []for background_image in background_images:location = {}result = re.findall('background-image: url\("(.*?)"\); background-position: (.*?)px (.*?)px;',background_image.get_attribute('style'))# print(result)location['x'] = int(result[0][1])location['y'] = int(result[0][2])image_url = result[0][0]location_list.append(location)image_url = image_url.replace('webp','jpg')# '替换url http://static.geetest.com/pictures/gt/579066de6/579066de6.webp'image_result = requests.get(image_url).contentimage_file = BytesIO(image_result) # 是一张无序的图片image = merge_image(image_file,location_list)return imagedef get_track(distance):# 初速度v=0# 单位时间为0.2s来统计轨迹,轨迹即0.2内的位移t=0.2# 位移/轨迹列表,列表内的一个元素代表0.2s的位移tracks=[]tracks_back=[]# 当前的位移current=0# 到达mid值开始减速mid=distance * 7/8print("distance",distance)global random_intrandom_int=8distance += random_int # 先滑过一点,最后再反着滑动回来while current < distance:if current < mid:# 加速度越小,单位时间的位移越小,模拟的轨迹就越多越详细a = random.randint(2,5)  # 加速运动else:a = -random.randint(2,5) # 减速运动# 初速度v0 = v# 0.2秒时间内的位移s = v0*t+0.5*a*(t**2)# 当前的位置current += s# 添加到轨迹列表if round(s)>0:tracks.append(round(s))else:tracks_back.append(round(s))# 速度已经达到v,该速度作为下次的初速度v= v0+a*tprint("tracks:",tracks)print("tracks_back:",tracks_back)print("current:",current)# 反着滑动到大概准确位置
tracks_back.append(distance-current)tracks_back.extend([-2,-5,-8,])return tracks,tracks_backdef get_distance(image1,image2):'''拿到滑动验证码需要移动的距离:param image1:没有缺口的图片对象:param image2:带缺口的图片对象:return:需要移动的距离'''# print('size', image1.size)
threshold = 50for i in range(0,image1.size[0]):  # 260for j in range(0,image1.size[1]):  # 160pixel1 = image1.getpixel((i,j))pixel2 = image2.getpixel((i,j))res_R = abs(pixel1[0]-pixel2[0]) # 计算RGB差res_G = abs(pixel1[1] - pixel2[1])  # 计算RGB差res_B = abs(pixel1[2] - pixel2[2])  # 计算RGB差if res_R > threshold and res_G > threshold and res_B > threshold:return i  # 需要移动的距离def main_check_code(driver,element):"""拖动识别验证码:param driver::param element::return:"""login_btn = driver.find_element_by_class_name('js-login')login_btn.click()element = WebDriverWait(driver, 30, 0.5).until(EC.element_to_be_clickable((By.CLASS_NAME, 'gt_guide_tip')))slide_btn = driver.find_element_by_class_name('gt_guide_tip')slide_btn.click()image1 = get_image(driver, '//div[@class="gt_cut_bg gt_show"]/div')image2 = get_image(driver, '//div[@class="gt_cut_fullbg gt_show"]/div')# 图片上 缺口的位置的x坐标# 2 对比两张图片的所有RBG像素点,得到不一样像素点的x值,即要移动的距离l = get_distance(image1, image2)print('l=',l)# 3 获得移动轨迹track_list = get_track(l)print('第一步,点击滑动按钮')element = WebDriverWait(driver, 30, 0.5).until(EC.element_to_be_clickable((By.CLASS_NAME, 'gt_slider_knob')))ActionChains(driver).click_and_hold(on_element=element).perform()  # 点击鼠标左键,按住不放import timetime.sleep(0.4)print('第二步,拖动元素')for track in track_list[0]:ActionChains(driver).move_by_offset(xoffset=track, yoffset=0).perform()  # 鼠标移动到距离当前位置(x,y)#time.sleep(0.4)for track in track_list[1]:ActionChains(driver).move_by_offset(xoffset=track, yoffset=0).perform()  # 鼠标移动到距离当前位置(x,y)time.sleep(0.1)import timetime.sleep(0.6)# ActionChains(driver).move_by_offset(xoffset=2, yoffset=0).perform()  # 鼠标移动到距离当前位置(x,y)# ActionChains(driver).move_by_offset(xoffset=8, yoffset=0).perform()  # 鼠标移动到距离当前位置(x,y)# ActionChains(driver).move_by_offset(xoffset=2, yoffset=0).perform()  # 鼠标移动到距离当前位置(x,y)print('第三步,释放鼠标')ActionChains(driver).release(on_element=element).perform()time.sleep(1)def main_check_slider(driver):"""检查滑动按钮是否加载:param driver::return:"""while True:try :driver.get('https://www.huxiu.com/')element = WebDriverWait(driver, 30, 0.5).until(EC.element_to_be_clickable((By.CLASS_NAME, 'js-login')))if element:return elementexcept TimeoutException as e:print('超时错误,继续')time.sleep(5)if __name__ == '__main__':try:count = 3  # 最多识别3次driver = webdriver.Chrome()while count > 0:# 等待滑动按钮加载完成element = main_check_slider(driver)main_check_code(driver,element)try:success_element = (By.CSS_SELECTOR, '.gt_success')# 得到成功标志success_images = WebDriverWait(driver,3).until(EC.presence_of_element_located(success_element))if success_images:print('成功识别!!!!!!')count = 0import syssys.exit()except Exception as e:print('识别错误,继续')count -= 1time.sleep(1)else:print('too many attempt check code ')exit('退出程序')finally:driver.close()
破解滑动验证码

 

 

 

iframe 页面的selenium如何定位

1、iframe有id属性

browser =webdriver.Chrome()# 获取一个浏览器对象
browser.get("http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable")  # 让该浏览器去访问该地址

browser.switch_to_frame('iframeResult')  # 找到id 为  'iframeResult'     iframe 中嵌套着另一个html 文档
source=browser.find_element_by_css_selector('#draggable')

 2. iframe 没有id ,或其id属性时变化的

下面为豆瓣的没id情况的定位:

 

id属性值时变化的:https://mail.126.com/

下面为豆瓣的没id情况的定位代码(126定位也用类似的方法):

from selenium import webdriverdriver = webdriver.Chrome()driver.get('https://www.douban.com/')# iframe 没有id 属性时
iframe=driver.find_elements_by_tag_name('iframe')[0]
driver.switch_to_frame(iframe)password_login = driver.find_element_by_xpath("//li[@class='account-tab-account']")   # element xpath 找一个元素

password_login.click()

 

转载于:https://www.cnblogs.com/knighterrant/p/10474722.html

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

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

相关文章

针对新手的Java EE7和Maven项目-第3部分-定义ejb服务和jpa实体模块

从前面的部分恢复 第1部分 第2部分 我们在第三部分继续介绍&#xff0c;我们已经有一个父pom&#xff0c;并且已经为我们的war模块定义了pom。 在我们的原始设置中&#xff0c;我们定义了我们的应用程序将包含一个ejb jar形式的服务jar。 这是我们的Enterprise Java Bean&…

计算机本地网络如何共享,本地网络共享怎么实现

本地网络共享可以满足多台电脑同时联网&#xff0c;台式电脑实现网络共享可以使用路由器&#xff0c;笔记本电脑事项网络共享需要使用无线路由器或者无线网卡。那么本地网络共享又是如何实现的呢&#xff0c;下面为大家详细介绍一下。通过路由器实现本地网络共享&#xff1a;第…

Git初始化配置以及配置github

1&#xff0c;配置用户名和邮箱&#xff08;这里是我github中配置的用户名和邮箱&#xff09;&#xff0c;执行下面命令后&#xff0c;在C:\Users\yaosq盘下会出现一个全局文件.gitconfig. git config --global user.name "这里换上你的用户名" git config --global…

数据知识栈

并发不适合胆小者 我们都知道并发编程很难正确实现。 这就是为什么在执行线程任务之后要进行大量的设计和代码审查会议。 您永远不会将并发问题分配给经验不足的开发人员。 仔细分析问题空间&#xff0c;提出设计&#xff0c;并记录和审查解决方案。 这就是通常处理线程相关任…

Spring Boot:快速启动MVC

我打算一年多以前写一篇关于Spring Boot的文章。 最后&#xff0c;我有时间和灵感。 因此&#xff0c;准备10到15分钟的高质量Spring教程。 我将用Gradle和嵌入式Tomcat演示Spring Boot的基础知识。 我使用Intellij IDEA而不是Eclipse&#xff0c;但是对于那些习惯Eclipse的人来…

布里斯托大学计算机科学专业排名,2021年布里斯托大学世界及专业排名 多个领域位居全英前十!...

它既是红砖大学的成员&#xff0c;也是罗素大学集团成员&#xff0c;在这所学校里共培养出了13位诺贝尔奖得主&#xff0c;这所学校就是布里斯托大学&#xff0c;该校的83%的研究成果都达到了世界领先水平&#xff0c;因此&#xff0c;越来越多的学生去布里斯托大学留学&#x…

Spring启动时的Spring社交示例,或者我如何不再担心和喜欢自动配置

对于Spring Boot 1.1.0.RC1&#xff0c;添加了自动配置和Spring Social的启动程序pom&#xff0c;这意味着我不必为pom添加一百个依赖关系&#xff0c;并且将为我处理许多毫无意义的Spring配置。 让我们来看一个例子。 我将实现一个两页的Web应用程序。 一个将显示给定用户的T…

Djang之cookie和session

一 会话跟踪 我们需要先了解一下什么是会话&#xff01;可以把会话理解为客户端与服务器之间的一次会晤&#xff0c;在一次会晤中可能会包含多次请求和响应。例如你给10086打个电话&#xff0c;你就是客户端&#xff0c;而10086服务人员就是服务器了。从双方接通电话那一刻起&a…

ASP.NET技巧(收集)

1、有没有办法让JavaScript的注释在客户端不可见呢&#xff1f; 答案很简单&#xff0c;就是&#xff1a;JavaScript注释 服务器端注释&#xff01; 行注释写法&#xff1a; //<%-- 这里写行注释 --%> 块注释写法&#xff1a; /*<%-- 这里写注释语句块&a…

Windows堆栈区别[转]

堆和栈的区别 (转贴) 非本人作也!因非常经典,所以收归旗下,与众人阅之!原作者不祥! 堆和栈的区别一、预备知识—程序的内存分配一个由c/C编译的程序占用的内存分为以下几个部分1、栈区&#xff08;stack&#xff09;— 由编译器自动分配释放 &#xff0c;存放函数的参数值&…

Tomcat启用HTTPS协议配置过程

Article1较为简洁&#xff0c;Article2较为详细&#xff0c;测试可行。 Article1 概念简介 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试…

springboot配置idea 热部署

背景&#xff1a; 在开发中&#xff0c;当我们修改代码之后&#xff0c;每次都要重新启动&#xff0c;很是浪费时间&#xff0c;在springboot中就有一种热部署方式&#xff0c;可以实现想要修改不需要每次都重新启动&#xff0c;保存即可生效 用法&#xff1a; 一、maven 添加 …

10分钟看懂Docker和K8S

作者&#xff1a;鲜枣课堂链接&#xff1a;https://www.jianshu.com/p/f1f94c6968f5 2010年&#xff0c;几个搞IT的年轻人&#xff0c;在美国旧金山成立了一家名叫“dotCloud”的公司。 这家公司主要提供基于PaaS的云计算技术服务。具体来说&#xff0c;是和LXC有关的容器技术。…

计算机专业论文关于天气预报的,关于天气预报论文范文写作 天气预报相关论文写作资料...

天气预报,本文是一篇关于天气预报论文范文&#xff0c;可作为相关选题参考,和写作参考文献。天气预报论文参考文献&#xff1a;每天吃过晚饭,严惠语都会准时打开电视,收看黑龙江电视台和云南电视台的天气预报节目.自从女儿考上云南大学,为了能攒够女儿下学期的费用,老公背起行李…

【快报】基于K2 BPM的新一代协同办公门户实践交流会

2014年2月28日&#xff0c;“基于BPM的新一代协同办公门户”用户实践交流活动在深圳金茂JW万豪酒店3楼Meet Room IV举办。本次会议由K2携手微软共同举办&#xff0c;邀请到的参会企业都是K2 的BPM老客户或对BPM新一代协同办公门户非常感兴趣的新朋友&#xff0c;他们有&#xf…

80个让你笑爆肚皮的程序员段子,不好笑算我输!

阅读本文大概需要 12 分钟。 1、折磨 对程序员的一般折磨&#xff1a;离奇的需求&#xff0c;对程序员的超级折磨&#xff1a;改三次需求~~~ 2、开发时间 项目经理说&#xff1a;给你三个人&#xff0c;多久可以完成&#xff1f;程序员&#xff1a;3个月&#xff01;那五个人呢…

腾讯TBS X5 WebView的简单使用

工作中经常涉及H5网页的加载工作&#xff0c;最多使用的就是安卓系统控件WebView&#xff0c;但是当网页内容比较多的时候&#xff0c;需要等待很久才能加载完&#xff0c;加载完后用户才能看到网页中的内容&#xff0c;这样用户需要等很久&#xff0c;体验很差。 那能不能边加…

python 内置标准库socketserver模块的思考

socketserver模块简化了编写网络服务器的任务, 在很大程度上封装了一些操作, 你可以看成是事件驱动型的设计, 这很不错。它定义了两个最基本的类--服务器类 BaseServer, 请求处理类 BaseRequestHandler. BaseServer 基本服务器类封装了基本的一些socket操作, socket原语中对so…

Spring 4.1和Java 8:java.util.Optional

由于Spring 4.1的Java 8的的java.util.Optional &#xff0c;容器对象可能会或可能不包含非空值&#xff0c;支持与RequestParam &#xff0c; RequestHeader和MatrixVariable 。 使用Java 8的java.util.Optional请确保参数永远不会为null 。 请求参数 在此示例中&#xff0c;…

Fibonacci again and again

Fibonacci again and again http://acm.hdu.edu.cn/showproblem.php?pid1848 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 12494 Accepted Submission(s): 5439 Problem Description任何一个大学生对菲波那…