python爬⾍爬取图⽚的简单步骤和实现代码
⽬录
本⼈略微学了⼀点python,主要是java。最近因为个⼈原因,需要爬⾍抓取图⽚,近期⾯向百度编程,顺路总结⼀下。
写爬⾍,⾸先需要获取⽹页信息,然后从⽹页的⼀堆标签中到有图⽚信息(地址)的,然后再利⽤⽹址把图⽚保存起来。
1. 如何获取⽹页信息
1). 直接从⽹络读取
from bs4 import BeautifulSoup
url = "www.baidu"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chr
ome/53.0.2785.143 Safari/537.36'
}
# url 是⽹页地址
web_data = (url, headers=headers)
soup = BeautifulSoup(, 'lxml')
读取的⽅法就是
web_data = (url, headers=headers)
soup = BeautifulSoup(, 'lxml')
2). 先将⽹页源码保存到本地,再读取
from bs4 import BeautifulSoup
file = open('C:/Users/tj/Desktop/test.html','r',encoding='utf-8')
妇女节问候语soup = BeautifulSoup(file,'lxml')
2. 分析获取到的⽹页信息,提取需要的信息(图⽚地址)
这⾥假设所有的图⽚都在img标签中,所有的img标签都在⼀个class属性名为beautiful的div(有且只有这么⼀个)中,图⽚的地址信息都在img的src属性中。
from bs4 import BeautifulSoup
import requests
# soup 有N多⽅法,find()、find_all()等(具体⽤法百度),
img_list=soup.find('div', class_="beautiful").find_all('img')
小学课外阅读指导课# 对 img_list进⾏遍历,获取其中的信息保存到数组中
li=[]
for x in range(len(img_list)):
print(x+1,": ",img_list[x].attrs["src"])
li.append(img_list[x].attrs["src"])
3. 使⽤request将图⽚保存到本地以及会碰到的⼀些问题
1)获取图⽚信息,再保存到本地⽂件中
"""
描述
enumerate() 函数⽤于将⼀个可遍历的数据对象(如列表、元组或字符串)组合为⼀个索引序列,同时列出数据和数据下标,⼀般⽤在 for 循环当中。Python 2.3. 以上版本可⽤,2.6 添加 start 参数。
语法
以下是 enumerate() ⽅法的语法:
enumerate(sequence, [start=0])
参数
sequence -- ⼀个序列、迭代器或其他⽀持迭代对象。
start -- 下标起始位置。
"""
from bs4 import BeautifulSoup
import requests
path="C:/Users/tj/Desktop/"
# i表⽰下标(从1开始), v表⽰数组的内容
for i,v in enumerate(li,start=1):
# 将图⽚地址(即v)再次放⼊request中
image = (v, timeout=10)
"""
存取图⽚过程中,出现不能存储int类型,故⽽,我们对他进⾏类型转换str()。
w:读写⽅式打开,b:⼆进制进⾏读写。图⽚⼀般⽤到的都是⼆进制。
"""
with open( path + str(i)+'.jpg', 'wb') as file:
# content:图⽚转换成⼆进制,进⾏保存。
file.t)
# 也可以使⽤如下⽅式保存到本地(和上⾯的保存到本地的⽅式其实⼀样)
dir = path + str(i)+'.jpg'
fp = open(dir, 'wb')
fp.t)
fp.close()
2). 超时处理
有些图⽚可能⽹址打不开,所以要添加超时处理:
from bs4 import BeautifulSoup
import requests
path="C:/Users/tj/Desktop/"
# i表⽰下标(从1开始), v表⽰数组的内容
for i,v in enumerate(li,start=1):幼儿园工作总结
try:
# 将图⽚地址(即v)再次放⼊request中
image = (v, timeout=10)
ptions.ConnectionError:
print('【错误】当前图⽚⽆法下载')
continue
with open( path + str(i)+'.jpg', 'wb') as file:
# content:图⽚转换成⼆进制,进⾏保存。
file.t)
⽹络请求不可避免会遇上请求超时的情况,在 requests 中,如果不设置你的程序可能会永远失去响应。
超时⼜可分为连接超时和读取超时。
连接超时指的是在你的客户端实现到远端机器端⼝的连接时(对应的是connect()),Request 等待的秒数。就算不设置,也会有⼀个默认的连接超时时间(据说是21秒)。
3). 读写超时
读取超时指的就是客户端等待服务器发送请求的时间。(特定地,它指的是客户端要等待服务器发送字节之间的时间。在 99.9% 的情况下这指的是服务器发送第⼀个字节之前的时间)。
简单的说,连接超时就是发起请求连接到连接建⽴之间的最⼤时长,读取超时就是连接成功开始到服务器返回响应之间等待的最⼤时长。 如果你设置了⼀个单⼀的值作为 timeout,如下所⽰:
r = ('github', timeout=5)
这⼀ timeout 值将会⽤作 connect 和 read ⼆者的 timeout。如果要分别制定,就传⼊⼀个元组:
r = ('github', timeout=(3.05, 27))
读取超时是没有默认值的,如果不设置,程序将⼀直处于等待状态。我们的爬⾍经常卡死⼜没有任何的报错信息,原因就在这⾥了。
EDG FLAG4). 超时重试
⼀般超时我们不会⽴即返回,⽽会设置⼀个三次重连的机制。
def gethtml(url):
i = 0
while i < 3:
try:
html = (url, timeout=5).text
return html
ptions.RequestException:
i += 1
其实 requests 已经帮我们封装好了。(但是代码好像变多了...)
from requests.adapters import HTTPAdapter
s = requests.Session()
print(time.strftime('%Y-%m-%d %H:%M:%S'))
try:
r = s.get('le.hk', timeout=5)
ptions.RequestException as e:
print(e)
print(time.strftime('%Y-%m-%d %H:%M:%S'))
max_retries 为最⼤重试次数,重试3次,加上最初的⼀次请求,⼀共是4次,所以上述代码运⾏耗时是20秒⽽不是15秒4. 使⽤urllib 将图⽚保存到本地以及会碰到的⼀些问题
1). 使⽤ urllib
urllib2 在 python3.x 中被改为quest
import urllib
#i表⽰下标,从1开始; v表⽰数组的值(图⽚的地址)
for i,v in enumerate(li,start=1):
2). 超时处理
有些图⽚可能⽹址打不开,所以要添加超时处理,但超时处理如下设置:
import urllib
import socket
#设置超时时间为30s
socket.setdefaulttimeout(30)
#i表⽰下标,从1开始; v表⽰数组的值(图⽚的地址)
for i,v in enumerate(li,start=1):
2). 再次下载
同时,还可以超时后 使⽤递归 再次下载:
电商做推广tips:新下载的⽂件会覆盖原来下载不完全的⽂件。
#设置超时时间为30s
socket.setdefaulttimeout(30)
def auto_down(url,filename):
try:
urllib.urlretrieve(url,filename)
except urllib.ContentTooShortError:
print 'Network conditions is not good.Reloading.'
auto_down(url,filename)
#i表⽰下标,从1开始; v表⽰数组的值(图⽚的地址)
for i,v in enumerate(li,start=1):
auto_down(v, path+str(x)+'.jpg')
但下载 会尝试好⼏次,甚⾄⼗⼏次,偶尔会陷⼊死循环,这种情况是⾮常不理想的。需要避免陷⼊死循环,提⾼运⾏效率。
import urllib
import socket
#设置超时时间为30s
socket.setdefaulttimeout(30)
#i表⽰下标,从1开始; v表⽰数组的值(图⽚的地址)
for i,url in enumerate(li,start=1):
try:
except socket.timeout:
count = 1
while count <= 5:
try:
break
except socket.timeout:
err_info = 'Reloading for %d time'%count if count == 1 else 'Reloading for %d times'%count
print(err_info)
count += 1
if count > 5:
print("downloading picture fialed!")
3). 显⽰下载进度
同时使⽤ quest.urlertriever() 的其他参数还可以显⽰出下载进度
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论