python爬虫抓取纯静态网站及其资源

news/2024/4/28 21:33:50/文章来源:https://blog.csdn.net/weixin_33953384/article/details/88762940

遇到的需求

前段时间需要快速做个静态展示页面,要求是响应式和较美观。由于时间较短,自己动手写的话也有点麻烦,所以就打算上网找现成的。

中途找到了几个页面发现不错,然后就开始思考怎么把页面给下载下来。

由于之前还没有了解过爬虫,自然也就没有想到可以用爬虫来抓取网页内容。所以我采取的办法是:

  1. 打开chrome的控制台,进入Application选项
  2. 找到Frames选项,找到html文件,再右键Save As...
  3. 手动创建本地的js/css/images目录
  4. 依次打开Frames选项下的Images/Scripts/Stylesheets,一个文件就要右键Save As...

这个办法是我当时能想到的最好办法了。不过这种人为的办法有以下缺点:

  1. 手工操作,麻烦费时
  2. 一不小心就忘记保存哪个文件
  3. 难以处理路径之间的关系,比如一张图片a.jpg, 它在html中的引用方式是images/banner/a.jpg,这样我们以后还要手动去解决路径依赖关系

然后刚好前段时间接触了一点python,想到可以写个python爬虫来帮我自动抓取静态网站。于是就马上动手,参考相关资料等等。

下面跟大家详细分享一下写爬虫抓取静态网站的全过程。

前置知识储备

在下面的代码实践中,用到了python知识、正则表达式等等,核心技术是正则表达式

我们来一一了解一下。

Python基础知识

如果你之前有过其他语言的学习经历,相信你可以很快上手python这门语言。具体学习可以上查看python官方文档或者其他教程。

爬虫的概念

爬虫,按照我的理解,其实是一段自动执行的计算机程序,在web领域中,它存在的前提是模拟用户在浏览器中的行为。

它的原理就是模拟用户访问web网页,获取网页内容,然后分析网页内容,找出我们感兴趣的部分,并且最后处理数据。

流程图是:

爬虫流程图

现在流行的爬虫主流实现形式有以下几种:

  1. 自己抓取网页内容,然后自己实现分析过程
  2. 用别人写好的爬虫框架,比如Scrapy

正则表达式

概念

正则表达式是由一系列元字符和普通字符组成的字符串,它的作用是根据一定的规则来匹配文本,最终可以对文本做出一系列的处理。

元字符是正则表达式中的保留字符,它有特殊的匹配规则,比如*代表匹配0到无穷多次,普通字符就是普通的abcd等等。

比如在前端中,常见的一个操作就是判断用户的输入是否为空,这时候我们可以先通过正则表达式来进行匹配,先过滤掉用户输入的两边空白值,具体实现如下:

function trim(value) {return value.replace(/^\s+|\s+$/g, '')
}// 输出 => "Python爬虫"
trim(' Python爬虫 ');

下面我们一起来具体了解一下正则表达式中的元字符。

正则表达式中的元字符

在上面,我们说过元字符是正则表达式中的保留字符,它有特殊的匹配规则,所以我们首先要了解经常出现的元字符。

匹配单个字符的元字符
  • .代表匹配一个任意字符,除了\n(换行符),比如可以匹配任意的字母数字等等
  • [...]表示字符组,里面可以有任意字符,它只会匹配当中的任意一个,比如[abc]可以匹配abc,这里值得注意的是,字符组里面的元字符有时候会被当成是普通字符,比如[-*?]等等,它代表的仅仅是-*?,而不是-代表区间*代表0到无穷次匹配?代表0或1次匹配
  • [^...][...]的含义相反,它的意思是匹配一个不属于[...]里面的字符,而不是不匹配[...]里面的字符,这两种说法虽然细微但是有很大差别,前者规定一定要匹配一个字符,这个切记。

例子:[^123]可以匹配4/5/6等等,但是不匹配1/2/3

提供计数功能的元字符
  • *代表匹配0次到无穷次,可以不匹配任何字符
  • +代表匹配1次到无穷次,至少匹配1次
  • ?代表匹配0次或1次
  • {min, max}代表匹配min次到max次,如a{3, 5}表示a至少匹配3-5次
提供位置的元字符
  • ^代表匹配字符串开头,如^a表示a要出现在字符串开头,bcd则不匹配
  • $代表匹配字符串结尾, 如A$表示A要出现在字符串结尾,ABAB则不匹配
其他元字符
  • |代表一个范围,可以匹配任意的子表达式,比如abc|def可以匹配abc或者def,不匹配abd
  • (...)代表分组,它的作用有界定子表达式的范围和与提供功能的元字符相结合,比如(abc|def)+代表可以匹配1次或1次以上的abc或者defdef,如abcabcabc,def
  • \i代表反向引用,i可以为1/2/3等整数,它的含义是指向上一个()里面匹配的内容。比如匹配(abc)+(12)*\1\2,如果匹配成功的话,\1的内容是abc,\2的内容是12或者空。反向引用通常用在匹配""或者''

环视

我理解的环视是界定当前匹配子表达式的左边文本和右边文本出现的情况,环视本身不会占据匹配的字符,它是当前子表达式的匹配规则但是本身不算进匹配文本。而我们上面说的元字符都代表一定的规则和占据一定的字符。环视可分为四种:肯定顺序环视、否定顺序环视、肯定逆序环视和否定逆序环视。它们的工作流程如下:

  • 肯定顺序环视:先找到环视中的文本在右侧出现的初始位置,然后从匹配到的右侧文本的最左的位置开始匹配字符
  • 否定顺序环视:先找到环视中的文本在右侧没有出现的初始位置,然后从匹配到的右侧文本的最左的位置开始匹配字符
  • 肯定逆序环视:先找到环视中的文本在左侧出现的初始位置,然后从匹配到的左侧文本的最右的位置开始匹配字符
  • 否定逆序环视:先找到环视中的文本在左侧没有出现的初始位置,然后从匹配到的左侧文本的最右的位置开始匹配字符
肯定顺序环视

肯定顺序环视匹配成功的条件是当前的子表达式能够匹配右侧文本,它的写法是(?=...),...代表要环视的内容。比如正则表达式(?=hello)he的意思是匹配包含hello的文本,它只匹配位置,不匹配具体字符,匹配到位置之后,才真正匹配要占用的字符是he,所以后面可以具体匹配llo等。

对于(?=hello)he而言,hello world可以匹配成功,而hell world则匹配失败。具体代码如下:

import rereg1 = r'(?=hello)he'print(re.search(reg1, 'hello world'))
print(re.search(reg1, 'hell world hello'))
print(re.search(reg1, 'hell world'))# 输出结果
<_sre.SRE_Match object; span=(0, 2), match='he'>
<_sre.SRE_Match object; span=(11, 13), match='he'>
None
否定顺序环视

否定顺序环视匹配成功的条件是当前的子表达式不能匹配右侧文本,它的写法是(?!...),...代表要环视的内容,还是上面的例子,比如正则表达式(?!hello)he的意思是匹配不是hello的文本,找到位置,然后匹配he。

例子如下:

import rereg2 = r'(?!hello)he'print(re.search(reg2, 'hello world'))
print(re.search(reg2, 'hell world hello'))
print(re.search(reg2, 'hell world'))# 输出结果
None
<_sre.SRE_Match object; span=(0, 2), match='he'>
<_sre.SRE_Match object; span=(0, 2), match='he'>
肯定逆序环视

肯定逆序环视匹配成功的条件是当前的子表达式能够匹配左侧文本,它的写法是(?<=...),...代表要环视的内容,比如正则表达式(?<=hello)-python的意思是匹配包含-python的子表达式,并且它的左侧必须出现hello,hello只匹配位置,不匹配具体字符,真正占用的字符是后面的-python。

例子如下:

import rereg3 = r'(?<=hello)-python'
print(re.search(reg3, 'hello-python'))
print(re.search(reg3, 'hell-python hello-python'))
print(re.search(reg3, 'hell-python'))# 输出结果
<_sre.SRE_Match object; span=(5, 12), match='-python'>
<_sre.SRE_Match object; span=(17, 24), match='-python'>
None
否定逆序环视

否定逆序环视匹配成功的条件是当前的子表达式不能匹配左侧文本,它的写法是(?<!...),...代表要环视的内容,比如正则表达式(?<!hello)-python的意思是匹配包含-python的子表达式,并且它的左侧必须不能出现hello。

例子如下:

import rereg4 = r'(?<!hello)-python'
print(re.search(reg4, 'hello-python'))
print(re.search(reg4, 'hell-python hello-python'))
print(re.search(reg4, 'hell-python'))# 输出结果
None
<_sre.SRE_Match object; span=(4, 11), match='-python'>
<_sre.SRE_Match object; span=(4, 11), match='-python'>

环视在对字符串插入某些字符很有效,你可以利用它来匹配位置,然后插入对应的字符,而不需要对原来的文本进行替换。

捕获分组

在正则表达式中,分组可以帮助我们提取出想要的特定信息。

指明分组很简单,只需要在想捕获的表达式中两端加上()就可以了。在python中,我们可以用re.search(reg, xx).groups()来获取到所有的分组。
默认的()中都指明了一个分组,分组序号为i,i从1开始,分别用re.search(reg, xx).group(i)来获取。

如果不想捕获分组可以使用(?:...)来指明。

具体例子如下:

import rereg7 = r'hello,([a-zA-Z0-9]+)'
print(re.search(reg7, 'hello,world').groups())
print(re.search(reg7, 'hello,world').group(1))
print(re.search(reg7, 'hello,python').groups())
print(re.search(reg7, 'hello,python').group(1))# 输出结果
('world',)
world
('python',)
python

贪婪匹配

贪婪匹配是指正则表达式尽可能匹配多的字符,也就是趋于最大长度匹配。

正则表达式默认是贪婪模式。

例子如下:

import rereg5 = r'hello.*world'
print(re.search(reg5, 'hello world,hello python,hello world,hello javascript'))# 输出结果
<_sre.SRE_Match object; span=(0, 36), match='hello world,hello python,hello world'>

由上可以看到它匹配的是hello world,hello python,hello world而不是刚开始的hello world。那如果我们只是想匹配刚开始的hello world,这时候我们可以利用正则表达式的非贪婪模式。

非贪婪匹配正好与贪婪匹配相反,它是指尽可能匹配少的字符,只要匹配到了就结束。要使用贪婪模式,仅需要在量词后面加上一个问号(?)就可以。

还是刚刚那个例子:

import rereg5 = r'hello.*world'
reg6 = r'hello.*?world'
print(re.search(reg5, 'hello world,hello python,hello world,hello javascript'))
print(re.search(reg6, 'hello world,hello python,hello world,hello javascript'))# 输出结果
<_sre.SRE_Match object; span=(0, 36), match='hello world,hello python,hello world'>
<_sre.SRE_Match object; span=(0, 11), match='hello world'>

由上可以看到这是我们刚刚想要匹配的效果。

进入开发

有了上面的基础知识,我们就可以进入开发环节了。

我们想实现的最终效果

本次我们的最终目的是写一个简单的python爬虫,这个爬虫能够下载一个静态网页,并且在保持网页引用资源的相对路径下下载它的静态资源(如js/css/images)。测试网站为http://www.peersafe.cn/index.html,效果图如下:

爬虫结果

开发流程

我们的总体思路是先获取到网页的内容,然后利用正则表达式来提取我们想要的资源链接,最后就是下载资源。

获取网页内容

我们选用python3自带的urllib.http来发出http请求,或者你可以采用第三方请求库requests

获取内容的部分代码如下:

url = 'http://www.peersafe.cn/index.html'# 读取网页内容
webPage = urllib.request.urlopen(url)
data = webPage.read()
content = data.decode('UTF-8')
print('> 网站内容抓取完毕,内容长度:', len(content))

获取到内容之后,我们需要把它保存下来,也就是写到本地磁盘上。我们定义一个SAVE_PATH路径,代表专门放置爬虫下载的文件。

# python-spider-downloads是我们要放置的目录
# 这里推荐使用os模块来获取当前的目录或者拼接路径
# 不推荐直接使用'F://xxx' + '//python-spider-downloads'等方式SAVE_PATH = os.path.join(os.path.abspath('.'), 'python-spider-downloads')

接下来就是为这个站点创建一个单独的文件夹了。这个站点文件夹的格式是xxxx-xx-xx-domain,比如2018-08-03-www.peersafe.cn。在此之前,我们需要写一个函数来提取出一个url链接的域名、相对路径、请求文件名和请求参数等等,这个在后续在根据资源文件的引用方式创建相对应的文件夹时也会用到。

比如输入http://www.peersafe.cn/index.html,那么将会输出:

{'baseUrl': 'http://www.peersafe.cn', 'fullPath': 'http://www.peersafe.cn/', 'protocol': 'http://', 'domain
': 'www.peersafe.cn', 'path': '/', 'fileName': 'index.html', 'ext': 'html', 'params': ''}

部分代码如下:

REG_URL = r'^(https?://|//)?((?:[a-zA-Z0-9-_]+\.)+(?:[a-zA-Z0-9-_:]+))((?:/[-_.a-zA-Z0-9]*?)*)((?<=/)[-a-zA-Z0-9]+(?:\.([a-zA-Z0-9]+))+)?((?:\?[a-zA-Z0-9%&=]*)*)$'regUrl = re.compile(REG_URL)# ...'''
解析URL地址
'''
def parseUrl(url):if not url:returnres = regUrl.search(url)# 在这里,我们把192.168.1.109:8080的形式也解析成域名domain,实际过程中www.baidu.com等才是域名,192.168.1.109只是IP地址# ('http://', '192.168.1.109:8080', '/abc/images/111/', 'index.html', 'html', '?a=1&b=2')if res is not None:path = res.group(3)fullPath = res.group(1) + res.group(2) + res.group(3)if not path.endswith('/'):path = path + '/'fullPath = fullPath + '/'return dict(baseUrl=res.group(1) + res.group(2),fullPath=fullPath,protocol=res.group(1),domain=res.group(2),path=path,fileName=res.group(4),ext=res.group(5),params=res.group(6))'''
解析路径eg:basePath => F:\Programs\python\python-spider-downloadsresourcePath => /a/b/c/ or a/b/creturn => F:\Programs\python\python-spider-downloads\a\b\c
'''
def resolvePath(basePath, resourcePath):# 解析资源路径res = resourcePath.split('/')# 去掉空目录 /a/b/c/ => [a, b, c]dirList = list(filter(lambda x: x, res))# 目录不为空if dirList:# 拼接出绝对路径resourcePath = reduce(lambda x, y: os.path.join(x, y), dirList)dirStr = os.path.join(basePath, resourcePath)else:dirStr = basePathreturn dirStr

上面的正则表达式REG_URL有点长,这个正则表达式能解析目前我遇到的各种url形式,如果有不能解析的,你可以自行补充,我测试过的url列表可以去我的github中查看。

首先一个最复杂的url链接(比如'http://192.168.1.109:8080/abc/images/111/index.html?a=1&b=2')来说,我们想分别提取出http://, 192.168.1.109:8080, /abc/images/111/, index.html, ?a=1&b=2。提取出/abc/images/111/的目的是为以后创建目录做准备,index.html是写入网页内容的名字。

有需要的可以深入研究一下REG_URL的写法,如果有更好的或者看不懂的,我们可以一起探讨。

有了parseUrl函数之后,我们就可以把刚刚获取网页内容和写入文件联系起来了,代码如下:

# 首先创建这个站点的文件夹
urlDict = parseUrl(url)
print('分析的域名:', urlDict)
domain = urlDict['domain']filePath = time.strftime('%Y-%m-%d', time.localtime()) + '-' + domain
# 如果是192.168.1.1:8000等形式,变成192.168.1.1-8000,:不可以出现在文件名中
filePath = re.sub(r':', '-', filePath)
SAVE_PATH = os.path.join(SAVE_PATH, filePath)# 读取网页内容
webPage = urllib.request.urlopen(url)
data = webPage.read()
content = data.decode('UTF-8')
print('> 网站内容抓取完毕,内容长度:', len(content))# 把网站的内容写下来
pageName = ''
if urlDict['fileName'] is None:pageName = 'index.html'
else:pageName = urlDict['fileName']pageIndexDir = resolvePath(SAVE_PATH, urlDict['path'])
if not os.path.exists(pageIndexDir):os.makedirs(pageIndexDir)pageIndexPath = os.path.join(pageIndexDir, pageName)
print('主页的地址:', pageIndexPath)
f = open(pageIndexPath, 'wb')
f.write(data)
f.close()

提取有用的资源链接

我们想要的资源是图片资源,js文件、css文件和字体文件。如果我们要对网页内容一一进行解析,利用分组,来捕获出我们想要的链接形式,比如images/1.pngscripts/lib/jquery.min.js

代码如下:

REG_RESOURCE_TYPE = r'(?:href|src|data\-original|data\-src)=["\'](.+?\.(?:js|css|jpg|jpeg|png|gif|svg|ico|ttf|woff2))[a-zA-Z0-9\?\=\.]*["\']'# re.S代表开启多行匹配模式
regResouce = re.compile(REG_RESOURCE_TYPE, re.S)# ...# 解析网页内容,获取有效的链接
# content是上一步读取到的网页内容
contentList = re.split(r'\s+', content)
resourceList = []
for line in contentList:resList = regResouce.findall(line)if resList is not None:resourceList = resourceList + resList

下载资源

在解析出资源链接后,我们要针对每一个资源链接进行检查,把它变成符合http请求的url格式,比如把images/1.png加上http头和刚刚的domain,也就是http://domain/images/1.png

下面是对资源链接进行处理的代码:

# ./static/js/index.js
# /static/js/index.js
# static/js/index.js
# //abc.cc/static/js
# http://www.baidu/com/static/index.js
if resourceUrl.startswith('./'):resourceUrl = urlDict['fullPath'] + resourceUrl[1:]
elif resourceUrl.startswith('//'):resourceUrl = 'https:' + resourceUrl
elif resourceUrl.startswith('/'):resourceUrl = urlDict['baseUrl'] + resourceUrl
elif resourceUrl.startswith('http') or resourceUrl.startswith('https'):# 不处理,这是我们想要的url格式pass
elif not (resourceUrl.startswith('http') or resourceUrl.startswith('https')):# static/js/index.js这种情况resourceUrl = urlDict['fullPath'] + resourceUrl
else:print('> 未知resource url: %s' % resourceUrl)

接着就是对每个规范的资源链接进行解析(parseUrl),提取出它要存放的目录和文件名等等,然后创建对应的目录。

在这里,我也处理了引用的其他网站的资源。

# 解析文件,查看文件路径
resourceUrlDict = parseUrl(resourceUrl)
if resourceUrlDict is None:print('> 解析文件出错:%s' % resourceUrl)continueresourceDomain = resourceUrlDict['domain']
resourcePath = resourceUrlDict['path']
resourceName = resourceUrlDict['fileName']if resourceDomain != domain:print('> 该资源不是本网站的,也下载:', resourceDomain)# 如果下载的话,根目录就要变了# 再创建一个目录,用于保存其他地方的资源resourceDomain =  re.sub(r':', '-', resourceDomain)savePath = os.path.join(SAVE_PATH, resourceDomain)if not os.path.exists(SAVE_PATH):print('> 目标目录不存在,创建:', savePath)os.makedirs(savePath)# continue
else:savePath = SAVE_PATH# 解析资源路径
dirStr = resolvePath(savePath, resourcePath)if not os.path.exists(dirStr):print('> 目标目录不存在,创建:', dirStr)os.makedirs(dirStr)# 写入文件
downloadFile(resourceUrl, os.path.join(dirStr, resourceName))

下载的函数downloadFile的代码是:

'''
下载文件
'''
def downloadFile(srcPath, distPath):global downloadedListif distPath in downloadedList:returntry:response = urllib.request.urlopen(srcPath)if response is None or response.status != 200:return print('> 请求异常:', srcPath)data = response.read()f = open(distPath, 'wb')f.write(data)f.close()downloadedList.append(distPath)# print('>>>: ' + srcPath + ':下载成功')except Exception as e:print('报错了:', e)

以上就是我们的开发全过程。

知识总结

本次开发用到的技术

  1. 利用urllib.http来发网络请求
  2. 利用正则表达式来解析资源链接
  3. 利用os系统模块来处理文件路径问题

心得体会

这篇文章也算是我这段时间学习python的一个实践总结,顺便记录下正则表达式的知识。同时我也希望能够帮助到那些想学习正则表达式和爬虫的小伙伴。

该python爬虫的源代码已经放在我的github上,有兴趣的小伙伴可以上去看看,满意的可以顺便给个Star,感谢支持。

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

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

相关文章

gcc离线安装 ubuntu 不用编译_「ubuntu安装gcc」ubuntu18.04安装gcc详细步骤(附问题集) - seo实验室...

ubuntu安装gcc首先是下载gcc包&#xff0c;可以在GCC的官方网站http://gcc.gnu.org/ 下载到各个版本。 目前最高版本是gcc-8.2.0。一、在安装gcc前,需要先安装 MPFR 、GMP 和MPCGCC编译需要mpfr和mpc(-->gmp、-->mpfr)库的支持&#xff0c;依次安装这几个库&#xff0c;其…

php无版权图库api,12个无版权限制的大图特供网站_交互设计教程

RaumrotRaumrot 的图库质量属上乘&#xff0c;都是高分辨率的免费图片&#xff0c;图片排版很舒服&#xff0c;很多都有复古风格。Unsplash网站每日更新十张图&#xff0c;不多&#xff0c;但质好。主打风景图片&#xff0c;大多数都有加上Instagram的特效滤镜&#xff0c;如果…

gitbook 使用,生成pdf,网站等内容

2019独角兽企业重金招聘Python工程师标准>>> GitBook 安装 GItBook官网 GitBook文档 个人推荐编辑器下载 安装 node.js gitbook 是基于 Node.js的命令行工具&#xff0c;下载地址 检测是否安装成功&#xff1a; $ node -v 10.14.2安装 GitBook $ npm install -g git…

网站设计解构:有效的交互设计框架和模式

网站设计解构:有效的交互设计框架和模式 基本信息 原书名&#xff1a; Web Anatomy: Interaction Design Frameworks that Work 原出版社&#xff1a; New Riders Press 作者&#xff1a; (美)Robert Hoekman Jr. Jared Spool 译者&#xff1a; 向怡宁 丛书名&#xff1a…

记一次网站被黑经历

问题原由 早上突然接到客户电话&#xff0c;网站在微信中无法打开&#xff0c;被微信拦截 在pc端访问网站&#xff0c;点击首页中任何一个url都会跳转到第三方网站&#xff0c;恍然大悟&#xff0c;网站是被黑了 问题分析 发现网站head被加入一下代码 发现js里面代码的如下&…

免费编程资源----网站篇

编程是一项必学功能&#xff0c;没必要拿着枯燥的书本在那里死啃&#xff0c;而是即刻动手才能学得快。所以我们要来看看这些免费编程资源。 1. Code/Racer Code/Racer是一个在线编程游戏&#xff0c;会强迫你快速编程&#xff0c;在编程游戏中&#xff0c;Code/Racer所属Treeh…

java setseed,基于webmagic的种子网站爬取

1. 概述因为无聊&#xff0c;闲来没事做&#xff0c;故突发奇想&#xff0c;爬个种子&#xff0c;顺便学习爬虫。本文将介绍使用Spring/Mybatis/webmagic等框架构建项目并爬取种子磁链。2. 项目搭建如下图为本项目的工程结构&#xff0c;主要代码实现在Spider包中。3. 数据库设…

外国优秀网页html,200个优秀的国外设计网站推荐

这个系列向大家推荐了200个优秀的国外设计网站&#xff0c;包括网页设计、名片设计、Logo设计和包装设计等等&#xff0c;设计师们可通过这些网站收集的优秀设计作品来获取灵感&#xff0c;进而设计出更具有创意的作品&#xff0c;设计师们也可以把自己得意的作品提交到这些网站…

Linux-运维网站综合架构分析

前言 如何规划一个网站的架构是十分重要的&#xff0c;一个好的网站架构可以给网站带来安全性&#xff0c;维护更加简单&#xff0c;服务更加稳定等等… 接下来便简要简述一下&#xff0c;一个网站的架构内容&#xff0c;其中涉及的服务器与所需软件 正文 集群架构概念图示 …

java无法验证证书_如何解决“证书无效,不能用于验证本网站的身份”错误?...

问题是&#xff0c;如何解决“证书无效并且不能用于验证本网站身份”的错误&#xff1f;。如何解决“证书无效&#xff0c;不能用于验证本网站的身份”错误&#xff1f;下面是详细信息&#xff1a;我有一个签名的小已经工作正常&#xff0c;直到我更新Java来8u25(1.8.0_25-B18)…

HTML制作菜鸟教程网站首页

这是我们要制作的网站首页 我们接下来将分块进行解析: 顶端模块: 我们将顶端模块分为两个div,分别通过float属性和margin属性达到我们想要的布局效果. 此处我试用的高和宽皆为像素定值,实际很多地方高都不需为定值,使其根据内容自适应大小即可.因为是像素设置的原因,所以当浏…

boot入门思想 spring_SpringBoot入门建站全系列(二十一)Mybatis使用乐观锁与悲观锁...

SpringBoot入门建站全系列&#xff08;二十一&#xff09;Mybatis使用乐观锁与悲观锁一、概述之前有两篇《SpringBoot入门建站全系列&#xff08;三&#xff09;Mybatis操作数据库》和《SpringBoot入门建站全系列&#xff08;四&#xff09;Mybatis使用进阶篇:动态SQL与分页》介…

cdn对php网站的加速效果,配置七牛自定义域名cdn加速,让你的网站飞起来

之前发过一篇是没有备案的&#xff0c;使用测试域名来缓存静态文件&#xff0c;效果也是杠杠的。如果你还没有备案&#xff0c;先看这篇文章吧&#xff0c;域名没备案使用七牛cdn加速 。步入正题了(为了节约博主发文的时间&#xff0c;尽量少用文字&#xff0c;多以图片展示&am…

360网站卫士能防服务器吗,360网站卫士测评

最近小编的主机商在主机控制后台开通了360网站卫士的功能&#xff0c;在了解了一些关于360网站卫士的功能之后&#xff0c;本站开始试用这款用于保障免受攻击&#xff0c;在开通一周之后&#xff0c;小编就来所说对这款360网站卫士应用的试用感受!首先让小编感受最为深刻的是“…

服务器绑定网站域名,服务器网站绑定域名

服务器网站绑定域名 内容精选换一换这个是浏览器的设置&#xff0c;没绑定SSL证书的&#xff0c;访问都会有这个提示。您可以为您的网站添加SSL证书。不一定。如果您需要通过HTTPS协议访问网站&#xff0c;就需要添加SSL证书&#xff0c;云速建站支持第三方免费SSL证书的添加。…

大型网站架构技术演进(史上最全)

1. 概述 本文以淘宝作为例子&#xff0c;介绍从一百个并发到千万级并发情况下服务端的架构的演进过程&#xff0c;同时列举出每个演进阶段会遇到的相关技术&#xff0c;让大家对架构的演进有一个整体的认知&#xff0c;文章最后汇总了一些架构设计的原则。 2. 基本概念 在介…

制作网站代码_网站制作的六个流程,一个都不能少

随着时代的发展&#xff0c;有新企业的诞生必然会伴随着旧企业的倒闭&#xff0c;新企业的成立必然会有网站制作的需要&#xff0c;那么这个网站制作的作用就不言而喻了&#xff0c;可以宣传企业的文化&#xff0c;加强企业在互联网上的传播。当然了&#xff0c;新建站的公司必…

python django 如何部署_【实战演练】Python+Django网站开发系列02-Django完整开发环境部署...

#本文欢迎转载&#xff0c;转载请注明出处和作者。上一篇我们讲到已经安装好了python3.8.1与django框架&#xff0c;并且直接启动了服务&#xff0c;但是目前并没有任何我们自定义的内容。我们网站开发的最终目标&#xff0c;是开发出一个简单的学生选课管理系统。系统需求&…

设计电子商务网站建设方案_成都婚纱摄影网站建设规划设计方案!

婚姻生活是人生道路中的一件大事儿&#xff0c;现阶段婚纱摄影行业相关的企业慢慢转型&#xff0c;大家对婚纱照的要求也逐渐转型为人性化、多元化,伴随着互联网的转型及当代生活的节奏,传统式的拍摄方法已逐渐被替代,成都婚纱摄影网站建设也是能快速获取顾客关注度十分重要的一…

网站迁移到新服务器的步骤_怎样将网站迁移至云服务器?需要注意什么?

经历过虚拟主机、VPS的使用&#xff0c;也慢慢从什么都不太熟悉的新用户变成了老油条&#xff0c;我知道&#xff0c;很多人把网站从日渐熟悉的传统服务器迁移到云服务器时&#xff0c;心里或多或少不是滋味&#xff0c;有不舍&#xff0c;当然更多的是未知的担忧。所以&#x…