Python3利用BeautifulSoup4批量抓取站点图片的代码
边学边写代码,记录下来。这段代码用于批量抓取主站下所有子网页中符合特定尺寸要求的的图片文件,支持中断。
原理很简单:使用BeautifulSoup4分析网页,获取网页<a/>和<img/>元素,对<a/>集合反复弹栈入栈,对<img/>集合进行筛选下载。
具体代码如下:import os
import sys
import time
import urllib.request
from urllib.parse import urljoin,urlparse
from bs4 import BeautifulSoup
from threading import Thread '''
class Download(Thread): #多线程下载代码1. 为每一个图片分配一个下载线程
def __init__(self,url,filepath):
Thread.__init__(self)
self.url = url
self.filepath = filepath def run(self):
length = 0
try:
opener = urllib.request.build_opener()
opener.addheaders = [('User-agent','Mozilla/5.0')]
urlhandle = opener.open(self.url,timeout = 30)
urlhead = urlhandle.info()
if 'Content-Length' in urlhead:
length = int(urlhead['Content-Length'])
data = urlhandle.read(10*1024)
while data:
with open(self.filepath,'ab+') as wf:
wf.write(data)
data = urlhandle.read(10*1024)
except Exception as ex:
print(self.url | '\n' + '× ' + str(ex))
try:
os.remove(self.filepath)
with open('/home/maple/Desktop/bad','a') as badFile: #超时未能完成下载则删除文件并将图片url记录到未下载链接列表中
badFile.write(self.url+'\n')
except:
pass
''' def maple(root):
tasks = [] #多线程集合
urls = [root] #待分析的网页链接
urld = [] #已分析并完成图片下载的网页链接
if os.path.exists('tmpUrls'): #读取本地待分析和已分析网页链接数据
with open('tmpUrls','r') as urlsFile:
urls = urlsFile.readlines()
for url in urls:
if url[0] == '' or url[0] == ' ':
urls.remove(url)
urls = [line[:-1] for line in urls]
if os.path.exists('tmpUrld'):
with open('tmpUrld','r') as urldFile:
urld = urldFile.readlines()
for url in urld:
if url[0] == '' or url[0] == ' ':
urld.remove(url)
urld = [line[:-1] for line in urld] try:
times =3 #设置网页读取失败后重试的次数
while urls:
curl = urls.pop()
urld.append(curl)
print('=================== Current Page: '+curl+' =======================')
try:
response = urllib.request.urlopen(curl,timeout = 5)
html = response.read()
data = html.decode('utf8')
soup = BeautifulSoup(data) #使用BeautifulSoup获取网页元素集
except Exception as ex: #读取网页失败,重试
print(ex)
if times > 0:
urls.append(curl)
urld.remove(curl)
times -= 1
else:
if curl in urld:
urld.remove(curl)
times = 3
continue
path = '/home/maple/Desktop/images/' count = 1
for list in soup.find_all('img'): #获取网页中所有图片链接
width = 0
height = 0
dict = list.attrs
if "src" in dict:
image = dict['src']
img = image[image.rfind('.'):]
if "alt" in dict: #该站点图片链接中提供的图片名属性,不同站点给出的属性可能不同甚至不一定给出图片名属性
fname = dict['alt']
filepath=os.path.join(path,fname+img)
else:
filepath = os.path.join(path,str(count)+img)
count +=1
if "width" in dict: #获取站点图片链接中提供的图片尺寸属性,width和height属性不一定给出
width = int(dict['width'])
if "height" in dict:
height = int(dict['height'])
num=1
while os.path.exists(filepath): #如获取的图片名与本地图片重名则自动按序重命名
fname,fext=os.path.splitext(filepath)
if '('+str(num-1)+')'+fext in filepath:
filepath = filepath.replace('('+str(num-1)+')'+fext,'('+str(num)+')'+fext)
else:
fname += '('+str(num)+')'
filepath = fname+fext
num +=1
for i in range(0,3): #图片下载失败后重试(如使用多线程部分的代码则无此循环)
try:
if (width == 0 or width >= 250) or (height ==0 or height >= 350):
length = 0
image_handle = urllib.request.urlopen(dict['src'],timeout = 5+i*10) #每次重试的超时时间依次递增
image_head = image_handle.info()
if 'Content-Length' in image_head: #获取图片实际大小
length = int(image_head['Content-Length'])
print(dict['src']+' ==== SIZE:{}*{} -- {}KB'.format(width,height,length/1000))
if length > 20*1000: #只下载超过一定大小的图片,避免下载网页中的图标或者链接图
with open(filepath, 'wb') as file:
image_data = image_handle.read()
file.write(image_data)
print('√')
break
'''
task = Download(dict['src'],filepath) #多线程下载代码2.为图片资源分配下载线程
task.setDaemon( True ) #将线程置为后台线程
task.start()
tasks.append(task) #启动线程并将线程加入线程集合中
'''
except Exception as ex:
if i < 2:
continue
else: #重试3次后依然下载失败则将图片url记录到未下载列表中
print('× '+str(ex))
try:
os.remove(filepath)
with open('/home/maple/Desktop/bad','a') as badFile:
badFile.write(dict['src']+'\n')
except:
pass
continue
'''
if len(tasks) >= 10:
while len([task for task in tasks if task.isAlive()]):
time.sleep(2)
tasks = []
''' for a in soup.find_all('a'): #获取当前页面中所有的链接地址,未分析的网页链接入栈
dict = a.attrs
if 'href' in dict:
url = dict['href']
if urlparse(url)[1]:
if urlparse(url)[1] == urlparse(curl)[1]:
pass
else:
url = urljoin(curl,url)
if url not in urls and url not in urld:
urls.append(url) except KeyboardInterrupt as kbi: #键盘终端,按下<C-c>终止程序,将已分析和未分析链接地址记录到本地
with open('tmpUrls','w') as urlsFile:
tmpList = [line + '\n' for line in urls]
urlsFile.writelines(tmpList)
with open('tmpUrld','w') as urldFile:
tmpList = [line + '\n' for line in urld]
urldFile.writelines(tmpList)
if __name__ == '__main__':
print("""
+++++++++++++++++++++++
version: python3.4
+++++++++++++++++=++++
""")
url = 'http://www.msnzx.com/' #示例站点(子页和图片太多,运行完成需要很长时间)
maple(url)
这段代码某些细节部分是专门针对 http://www.msnzx.com/ 这个站点的,下载其他站点数据仅需要微调一下就行了。其中分析网页直接使用了强大的第三方模块BeautifulSoup4,方便快捷。下载图片部分的实方式实在太多,上述代码中包含了2种下载方式:
1、直接使用url.request读写流一次性下载,下载任意文件时程序都是阻塞的。这种方式适合下载size较小的图片。图片要么完全下载,要么完全不下载(得到的本地文件size = 0),网络条件不佳的时候可以捕获超时异常记录未成功下载的图片url。
2、以多线程的方式下载,为每个图片资源分配一个下载线程。上述程序的注释部分即是多线程下载代码。这种方式下载迅速,就算网络不佳,也能下载到图片的部分内容。
另外还有很多下载方式,如单独调用其他模块(如urllib.request中的urlretrieve,之前文章中实现的文件多线程下载模块download)或者系统工具如wget,curl等。这种直接调用的方式能够为每一个图片分配多线程进行下载。实现方式也最简单。
Python3利用BeautifulSoup4批量抓取站点图片的代码的更多相关文章
- 使用python来批量抓取网站图片
今天"无意"看美女无意溜达到一个网站,发现妹子多多,但是可恨一个page只显示一张或两张图片,家里WiFi也难用,于是发挥"程序猿"的本色,写个小脚本,把图片扒 ...
- Hibernate学习---第十一节:Hibernate之数据抓取策略&批量抓取
1.hibernate 也可以通过标准的 SQL 进行查询 (1).将SQL查询写在 java 代码中 /** * 查询所有 */ @Test public void testQuery(){ // ...
- Python3简单爬虫抓取网页图片
现在网上有很多python2写的爬虫抓取网页图片的实例,但不适用新手(新手都使用python3环境,不兼容python2), 所以我用Python3的语法写了一个简单抓取网页图片的实例,希望能够帮助到 ...
- 使用IDM批量抓取音效素材下载
IDM下载器的站点抓取功能,能够抓取网站上的图片.音频.视频.PDF.压缩包等等文件.更重要的是,能够实现批量抓取操作,省时省力.今天就来看一下,如何用IDM巧妙的批量抓取音效素材. 1.进入音效合辑 ...
- 抓取网页图片的脚本(javascript)
抓取网页图片的脚本(javascript) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24172223 脚本内容 (没有换行) ...
- PHP抓取远程图片教程(包含不带后缀图片)
之前做微信登录开发时候,发现微信头像图片没有后缀名,传统的图片抓取方式不奏效,需要特殊的抓取处理.所以,后来将各种情况结合起来,封装成一个类,分享出来. 创建项目 作为演示,我们在www根目录创建项目 ...
- php远程抓取网站图片并保存
以前看到网上别人说写程序抓取网页图片的,感觉挺神奇,心想什么时候我自己也写一个抓取图片的方法! 刚好这两天没什么事,就参考了网上一个php抓取图片代码,重点借鉴了 匹配img标签和其src属性正则的写 ...
- 百度UEditor编辑器关闭抓取远程图片功能(默认开启)
这个坑娘的功能,开始时居然不知道如何触发,以为有个按钮,点击一下触发,翻阅了文档,没有发现,然后再网络上看到原来是复制粘贴非白名单内的图片到编辑框时触发,坑娘啊............... 问题又来 ...
- 使用HtmlAgilityPack批量抓取网页数据
原文:使用HtmlAgilityPack批量抓取网页数据 相关软件点击下载登录的处理.因为有些网页数据需要登陆后才能提取.这里要使用ieHTTPHeaders来提取登录时的提交信息.抓取网页 Htm ...
随机推荐
- 虚拟机下linux安装mysql,apache和php
由于腿伤了,卧床在家折腾下linux,尝试用虚拟机装mysql,apche和php.中间各种波折,装了好几天,觉得有些经验还是要记录下来,让自己别忘了:) 按照下面这篇文章的方法,基本可以顺利安装成功 ...
- JS中offsetTop、clientTop、scrollTop、offsetTop各属性介绍
这里是javascript中制作滚动代码的常用属性 页可见区域宽: document.body.clientWidth;网页可见区域高: document.body.clientHeight;网页可见 ...
- MYSQL 优化常用方法
1.选取最适用的字段属性 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽 ...
- c++ Primer 第四版 第一阶段 const总结
由于期末值考一门软件安全,所以果断看起c++Primer ,因为之前看谭浩强的c++感觉没什么用啊.所以这本书每阶段做个总结!!! 1.Const限定符作用: 在for循环中上限应该用一个固定变量来设 ...
- a different object with the same identifier value was already associated with the session:错误;
当出现a different object with the same identifier value was already associated with thesession时,一般是因为在h ...
- 这是个简单的UTF8转码的小Demo
NSString *name = @"你好啊"; NSString *string = [NSString stringWithFormat:@"%@",nam ...
- asp.net的JSONHelper 类
调用方法: ){ jsons = json.ToString();}else{ jsons = @"{success:false}";}return jsons; JS ...
- Neural Network学习(一) 最早的感知机:Perceptron of Rosenblatt
1. Frank Rosenblatt 首先介绍的是神经网络的开山祖师,先放张图拜拜 Frank Rosenblatt出生在纽约,父亲是医生,其1956年在Cornell大学拿到博士学位后,留校任教, ...
- 10.openssl x509
主要用于输出证书信息.也能够用于签名.自签名.转换证书格式.还原证书为证书请求等.该命令非常强大,几乎实现了伪命令req,ca,verify,crl的所有功能,最牛的一点是该命令不需要通过配置文件就能 ...
- genymotion启动虚拟机遇到问题解决方法步骤
通过在不做任务设置时启动genymotion,会遇到一些问题: 会弹出类似如下问题: 要解决这样问题,首先要知道是什么问题,一般按提示在VitualBox中启动虚拟机就可以知道是什么问题. “To f ...