以下网页有102个图标,如何一次性爬取?
http://www.pp3.cn/icon/size/16_16/2011/1128/831.html
试试以下小程序:
import re
import urllib.request
import os
#1 抓取网页(网页上有图片地址)
url = 'http://www.pp3.cn/icon/size/qita/2011/1128/758.html'
req = urllib.request.urlopen(url)
buf = req.read()
req.close()
#2 获取图片地址
# 下面4句截取url的前半截,如http://www.pp3.cn(一些图片是相对地址)
i = url.find("/",9)
url0 = url
if i > 0 :
url0 = url[:i]
buf = buf.decode('gb2312') # 有些网页编码是utf-8,要一致
listurl = re.findall(r'img src=.[^\'\"]+\.png',buf)
for i in range(len(listurl)): # 把字符img src="去掉
listurl[i]=listurl[i].replace('img src="',"")
if not re.match("http",listurl[i]): # 如果是相对地址,加上上面提取的基地址
listurl[i]=url0 + listurl[i]
print(listurl[i]) # 将图片地址列表打印一下
#3 抓取图片并保存到本地
fpath = "D:\\pic2\\"
if not os.path.isdir(fpath):
os.mkdir(fpath)
i = 0
for url in listurl:
f=open(fpath + str(i)+'.png','wb')
req = urllib.request.urlopen(url)
buf = req.read()
f.write(buf)
f.close()
i+=1
有四个关键点:
1 网页的编码:有的是GB2312,有的是utf-8。
2 有的网站服务器做了反爬虫设置,需要写较复杂的代码来绕过。
3 图片网址正则表达式的设置。如上述的
r'img src=.[^\'\"]+\.png'
图片的HTML的写法:
img src='http//…/picPath/…/.png'
img src='http//…/picPath/…/.jpg'
img src="http//…/picPath/…/.jpg"
img src="picPath/…/.jpg"
要通过适当的正则表达式来构建上述字符串表示规律。
3.1 圆点“.”表示除'\n'以外的任意字符。上述可以表示单引号或双引号,如果没有其它字符,如在引用前还有一个字符,可多写一个圆点.。
3.2 “[^\'\"]+”表示一串除了单引号或双引号以外的任意数量的其它字符。直到遇到“\.png”为止(可能出现贪婪匹配)。“[]”表示列举,“^”表示非,排除后面紧跟的字符;“\”表示转义,转义是指转变原本的含义,单引号和双引号原本是用来界定字符的,用转义符来放弃这个用途,用做普通字符。加号“+”表示一个或多个前面的字符表示。
3.3 "\.png"表示圆点.和图片的类型png。
上面说到贪婪匹配,要设置为非贪婪匹配,用小括号分组加一个问号即可:
reg = r'img src=.([^\'\"]+\.png)?'
如果出现问题,可以相看原网页的图片地址编写格式及规律,简单化处理。
如图片地址都有如下规律,
http://www.pp3.cn/uploads/allimg/111128/1-11112…….png
可将正则表达式简单写为:
http://www.pp3.cn/uploads/allimg/111128/1-11112\S*.png
“/S*”表示任意数量非空白字符。
如果有多个网页,可以将上述代码写成函数形式,循环调用:
import re # 正则表达式
import urllib.request # 从服务器请求返回资源
import os # 文件和目录操作
import socket # 套接字操作
#socket.setdefaulttimeout(20) # 设置socket层的超时时间为20秒
def gethtml(url): #1 抓取网页html内容
with urllib.request.urlopen(url) as req:
buf = req.read()
return buf
def getImg(buf,codec,fpath,rege): #2 从html筛选图片地址到list
# 下面4句截取url的前半截,如http://www.pp3.cn(一些图片是相对地址)
i = url.find("/",9)
url0 = url
if i > 0 :
url0 = url[:i]
buf = buf.decode(codec)
listurl = re.findall(reg,buf) #reg是正则表达式
print("准备下载图片数量:",len(listurl))
for i in range(len(listurl)):
#listurl[i]=listurl[i].replace('img src="',"") # 把字符img src="去掉
if not re.match("http",listurl[i]):
listurl[i]=url0 + listurl[i]
print(listurl[i])
#3 抓取图片并保存到本地
if not os.path.isdir(fpath):
os.mkdir(fpath)
i = 0
'''
for imgurl in listurl:
urllib.request.urlretrieve(imgurl,fpath + str(i)+'.jpg')
i+=1
'''#下面的操作方式要快一点
for imgurl in listurl:
f=open(fpath + str(i)+'.jpg','wb') # 新建空白图片文件
req = urllib.request.urlopen(imgurl) # 获取网页图片文件
buf = req.read() # 读取网站上图片文件内容
f.write(buf) # 将网站上图片内容写入新建的图片文件
f.close()
i+=1
# 四处内容需要确认:1 网页url; 2 网页编码UTF-8或gb2312;
# 3 图片扩展名jpg或png(两处); 4 保存的文件夹
codec = 'gb2312'
reg = r'img src=.([^\'\"]+\.png)?'
webpages = ['http://www.pp3.cn/icon/size/qita/2011/1128/758.html', # 需提取图片的网址可写到列表内
'http://www.pp3.cn/icon/size/32_32/2011/1128/768.html'
]
i = 0
for url in webpages:
buf = gethtml(url)
fpath = "D:\\" + str(i) +"\\"
print(getImg(buf,codec,fpath,reg)) # 函数循环调用
i+=1
url = 'http://culture.ifeng.com/c/7vm9bFrvQpl'
codec = 'utf-8'
buf = gethtml(url)
reg = r'img src=..([^\'\"]+\.jpeg)?'
fpath = 'D:\\A\\'
print(getImg(buf,codec,fpath,reg)) # 函数单独调用
图片格式不同的较灵活的写法:
import re
import urllib.request
import os
from itertools import islice # 跳过可迭代对象的开始部分
# fpath = "D:\\pic2\\"
# 分析网页文本、提到图片超链接到list,逐一将list项保存到图片文件
# ① 要注意网页的字符编码,可在网页查看
# ② 要注意网站图片的url格式规律
# ③ 要注意图片的扩展名
# ④ 一次老是抓取不成功,原因是第三张无法打开,后跳过
#"""
# 1 获取网页文本
url = 'http://www.pp3.cn/icon/size/16_16/2011/1128/831.html'
#url = 'http://www.pp3.cn/icon/size/16_16/2011/1128/835.html'
# 1.1 url没加header的写法
req = urllib.request.urlopen(url)
buf = req.read()
req.close()
# 1.2 在urllib中添加headers不同的写法,需要headers是字典或元组
"""
headers = { # 如有反爬,可添加网页自己的header
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
}
req = urllib.request.Request(url=url,headers=headers)
file = urllib.request.urlopen(req)
buf = file.read()
"""
#2 多网页文本中解析出图片地址
i = url.find("/",9) # 本句及下面三句截取url的前半截
url2 = url
if i > 0 :
url2 = url[:i]
#buf = buf.decode('UTF-8')
buf = buf.decode('gb2312')
#picType = '.jpg'
#picType = '.jpeg'
picType = '.png'
#picType = '.gif'
#listurl = re.findall(r'http:.[^"]+\.jpg',buf)
if picType == '.jpg' :
listurl = re.findall(r'img src=.([^\"^\']+\.jpg)?',buf)
if picType == '.jpeg' :
listurl = re.findall(r'img src=.([^\"^\']+\.jpeg)?',buf)
if picType == '.png' :
listurl = re.findall(r'img src=.([^\"^\']+\.png)?',buf)
if picType == '.gif' :
listurl = re.findall(r'img src=.([^\"^\']+\.gif)?',buf)
for i in range(len(listurl)): # 把字符img src="去掉
listurl[i]=listurl[i].replace('img src="',"")
if not re.match("http",listurl[i]):
listurl[i]=url2 + listurl[i]
print(listurl[i])
#"""
"""
# 已知图片url,只是序号不同
listurl = []
strs = "http://www.graphiscnn.com/evahbcms/upload/image/196/00"
for x in range(2,55):
listurl.insert(x,strs+str(x)+".jpg")
"""
#3 抓取图片并保存到本地
i = 1
fpath = "D:\\pic3\\"
if not os.path.isdir(fpath):
os.mkdir(fpath)
#for url in listurl: # 列表的第三张无法打开,导致失败
for url in islice(listurl, 4, None):
f=open(fpath + str(i)+picType,'wb')
req = urllib.request.urlopen(url)
buf = req.read()
f.write(buf)
print(i,picType)
f.close()
i+=1
"""
# UnicodeEncodeError: 'UCS-2' codec can't encode characters
# in position 73-73: Non-BMP character not supported in Tk
# 爬取的HTML页面中包含了Unicode下无法识别的字符,添加标识为①-③的三行代码
import requests
import sys # ①
non_bmp_map = dict.fromkeys(range(0x10000,sys.maxunicode + 1),0xfffd) # ②
url = 'https://p.51vv.com/vp/kws2X4IT'
html = requests.get(url,headers=headers)
print(html.request.headers)
html = str(html.text).translate(non_bmp_map) # ③
print(html)
"""
运行:
提取到的图片:
End
格语法:
注意:颜色使用格式有三种:rgb(x,x,x) #xxxxxx colorname
<table width=""></table>指定表格的宽度大小(使用数字pixel或%)
<table border=""></table>设定表格边框大小(使用数字pixel)
<table align=""></table>表格位置,置左,为默认值
align属性:left(左对齐表格,默认值)、right(右对齐表格)、center(居中对齐表格)
<table bgcolor=""></table>设定表格的背景颜色
<table cellpadding=""></table>指定内容与网格线之间的间距(使用数字pixel或%)
<table cellspacing=""></table>指定网格线与网格线之间的距离(使用数字pixel或%)
<table border="1" cellspacing="0" cellpadding="0">
通常表格, 这两个参数都设置为 0 。
<table rules="rows"></table>规定内侧边框的哪个部分是可见的。(兼容性差)
rules属性:none 没有线条。
groups 位于行组和列组之间的线条。
rows 位于行之间的线条。
cols 位于列之间的线条。
all 位于行和列之间的线条。
<table summary="Monthly savings for the Flintstones family"></table>
定义了表格内容的摘要:
表格结构:
在使用表格进行布局时, 可以将表格划分为头部、主体和页脚, 具体如下所示:
<thead></thead>:用于定义表格的头部, 必须位于<table></table>标记中, 一般包含网页的logo和导航等头部信息。
<tfoot></tfoot>:用于定义表格的页脚, 位于<table></table>标记中<thead></thead>标记之后, 一般包含网页底部的企业信息等。
<tbody></tbody>:用于定义表格的主体, 位于<table></table>标记中<tfoot></tfoot>标记之后, 一般包含网页中除头部和底部之外的其他内容。
注意:在没有<tbody></tbody>比较的情况下, 浏览器会自动添加<tbody></tbody>标记。
<table bordercolor=""></table>设定表格边框的颜色
<table cols=""></table>指定表格的栏数
<table height=""></table>指定表格的高度大小(使用数字)
<table background=""></table>背景图片的URL=就是路径网址(默认是repeat:水平和垂直方向重复)
<table bordercolordark=""></table>设定表格暗边框的颜色
<table bordercolorlight=""></table>设定表格亮边框的颜色
<tr align=""></tr> 定义表格行的内容对齐方式。
align属性值:right、left、center、justify、char
<tr bgcolor=""></tr> 规定表格行的背景颜色。
<tr valign=""></tr> 规定表格行中内容的垂直对齐方式。
valign属性值right、left、center、justify、char
<td colspan=""></td>指定储存格合并栏的栏数(使用数字)
<td rowspan=""></td>指定储存格合并列的列数(使用数字)
<td align=""></td> 调整表格字段之左右对齐
<td bgcolor=""></td> 设定表格字段之背景颜色
<td colspan="" rowspan=""></td> 表格字段的合并
<td valign=""></td> 调整表格字段之上下对齐
<td width=""></td> 调整表格字段宽度
<td nowrap="nowrap"></td> 规定表格单元格中的内容不换行(注意只有一个值:nowrap)
<caption></caption>为表格加上标题
<caption align="">设定表格标题位置
align属性:left, center(默认值), right
<th></th> 定义表头(粗体居中)
细表格边框
<table border="1" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="158" height="68">
<tr>
<td width="158" height="68"></td>
</tr>
</table>
表格创建后浏览器会自动添加<tbody>标签
一篇文章中,小海前端(头条号)为小伙伴们介绍了CSS3中新增的border-image属性,该属性主要用于为容器的边框添加图片。本篇文章,继续为大家讲解该属性的用法和CSS3中对该属性的一些细节要求。
尚未阅读上一篇文章的小伙伴请先阅读上一篇文章,上一篇文章讲解了border-image属性及其派生属性的基础用法。
承接文章:为容器的边框添加图片,CSS3新增的边框图片属性,一种新颖的用法
技术等级:中级 | 适合有一定的CSS基础的人士阅读。
该组属性的兼容性暂时还不是特别好,建议大家使用火狐浏览器(Firefox)来尝试该属性的各个效果。
希望收藏了这篇文章的你同时也可以关注一下“小海前端”的头条号,因为这些文章都是连载的,并且是经过系统的归纳和总结的。塌下心来认真阅读,你一定会学到对你有用的知识。
本篇文章涉及到的CSS3属性问题:
border-image-slice属性的使用细节
border-outset属性的用法
border-image-width属性和border-width属性的区别
border-image属性和border属性的冲突性
各个浏览器内核的兼容性
一、border-image-slice属性的使用细节:
上一篇文章中讲到,border-image-slice是用来设置边框图片的切片属性的。该属性的取值为一个不带单位的数值,默认单位为像素,但是不用书写px。该属性设置的数值可以将边框图片划分为9个区域,并贴到边框的9个不同位置。
这里还以上一篇文章中宽度和高度均为90像素的图片为例,该图片存放在一个名为images的文件夹中,图片的文件名为ball.jpg,图片中每个圆形的直径均为30像素。
素材图 ball.jpg
对于该属性,CSS3对于它的使用方法还有以下几个细节要求:
当切片的上下偏移之和大于等于图像的高度,且左右偏移之和大于等于图像的宽度。则容器只有四个角可以获得边框图片的切片,而容器的边无法获得任何图片。
CSS代码如下所示:
border-image:url(../images/ball.jpg) 60 70 50 30/30px round
上述代码指出,上切片尺寸为60像素,右切片尺寸为70像素,下切片尺寸为50像素,左切片尺寸为30像素。上下切片的偏移之和为110像素,左右切片的偏移之和为100像素,这两个值均超过了图片90像素的宽高尺寸。因此只有容器的四个角可以得到边框图像。最终效果如下图所示:
实体效果图
当切片的上下偏移量都大于等于图像的高度,且左右偏移量都大于等于图像的宽度。则容器的四个角可以获得完整的边框图像。
CSS代码如下所示:
border-image:url(../images/ball.jpg) 90 100 120 130/30px round
上述代码指出,上切片尺寸为90像素,右切片尺寸为100像素,下切片尺寸为120像素,左切片尺寸为130像素。每一个方向的切片偏移量均大于等于图片90像素的宽度和高度值。因此容器的四个角可以获得完整的边框图像。同样,边依然无法得到任何切片图像。
最终效果如下图所示:
实体效果图
border-image-slice属性还有一个可以放在切片数量后面的取值。当具有该取值并设置为“fill”时,边框图片中5号圆形就会显示在容器的内部。如果没有该取值,边框图片中5号圆形就不会显示在容器内部。
CSS代码如下所示:
border-image:url(../images/ball.jpg) 30 fill/30px round
最终效果如下图所示:
实体效果图
二、border-outset属性的用法:
该属性用来对边框图像实现向外扩张的效果。该属性的取值为带有单位的数值。同时该属性也是可以结合border-image属性单独使用的。
CSS代码如下所示:
border-image:url(../images/ball.jpg) 30/30px round
border-outset:30px;
上述代码会让边框图像在显示的同时向外扩张30像素。请小伙伴们自行操作并尝试。
三、border-image-width属性和border-width属性的区别:
border-width属性可以单独使用,适用于设置具有颜色的边框宽度。
border-image-width属性不可以单独使用,必须在border-image属性取值内部固定的位置处使用。该属性主要用于设置具有图像的边框宽度。
这两个属性是可以同时使用的。
当容器内部具备文本内容时,我们发现,文本内容出现在了边框图片的位置处。为了方便小伙伴们观察,我把文本内容调整成了黄色。如下图的左侧部分。
实体效果图
此时调整border-width属性,为了让边框宽度生效,还需要设置边框样式border-style。为了不让容器的大小发生变化,添加box-sizing属性。为了便于查看,我把文本内容调整成了红色。如上图右侧部分。
CSS代码如下所示:
border-image: url(../images/ball.jpg) 30/30px round;
border-width: 30px;
border-style: solid;
box-sizing: border-box;
color:#ff0000;
四、border-image属性和border属性的冲突性:
CSS3规定,带有颜色的边框和边框图片不得同时存在,并且当border-image属性和border属性同时存在时,border-image是不起作用的。
CSS代码如下所示。
border-image:url(../images/ball.jpg) 30/30px round;
border:solid 10px #ff5857;
上述代码执行后,容器会带有10像素的边框,而不带有边框图片。小伙伴们可以自行尝试。
五、各个浏览器内核的兼容性:
CSS3的属性中还有许多都是浏览器不能完全兼容的,有的属性兼容部分浏览器,有的属性被浏览器部分兼容。那么,要对所有的浏览器都得到相同的外观,应该如何处理呢?
可以采用为CSS属性的兼容性前缀来解决这个问题。
-ms-,适用于具有Trident内核的IE系列浏览器。
-webkit-,适用于具有webkit内核的浏览器,例如Safari浏览器、360安全浏览器等。
-moz-,适用于Firefox浏览器。
-o-,适用于Opera浏览器。
因此,border-image属性要实现浏览器全兼容可以使用下列代码:
border-image:url(../images/ball.jpg) 30/30px round
-webkit-border-image:url(../images/ball.jpg) 30/30px round
-moz-border-image:url(../images/ball.jpg) 30/30px round
-o-border-image:url(../images/ball.jpg) 30/30px round
-ms-border-image:url(../images/ball.jpg) 30/30px round
不过通过实际操作,我发现border-image属性即使加上了浏览器兼容性前缀,也不能达到满意的效果。CSS3中还有许多属性都不能达到最满意的兼容性,我们只能等待CSS3完备的计划出台,并尽快得到大部分浏览器厂商的支持和认可。
在头条上发表的这些文章都是从前端开发的基础开始一步一步讲起的。我非常希望能有更多的前端开发初学者通过我写的文章,逐步学到一定的知识,甚至慢慢有了入门的感觉。这些文章都是我这几年教学过程中的经验,每写一篇时我都尽量把握好措辞,用简单易懂的语言描述,同时精心设计版面,让版面更加丰富,激发阅读兴趣。所以,每一篇文章可能篇幅不长,但是都要耗费小海老师很久的时间。
希望收藏了这篇文章的你同时也可以关注一下“小海前端”的头条号,因为这些文章都是连载的,并且是经过系统的归纳和总结的。塌下心来认真阅读,你一定会学到对你有用的知识。
关注“小海前端”,我会继续为大家奉上更加深入的前端开发文章,也希望更多的初学者跟着学下去,我们共同将前端开发的路努力坚持的走下去。
下一篇文章中,小海前端(头条号)会为小伙伴们讲解CSS3中实现多列布局的属性。这组属性解决了在CSS2时必须要对容器进行浮动才能在一行内显示多列的问题。希望小伙伴们不要错误。
*请认真填写需求信息,我们会在24小时内与您取得联系。