边学边写代码,记录下来。这段代码用于批量抓取主站下所有子网页中符合特定尺寸要求的的图片文件,支持中断。

原理很简单:使用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批量抓取站点图片的代码的更多相关文章

  1. 使用python来批量抓取网站图片

    今天"无意"看美女无意溜达到一个网站,发现妹子多多,但是可恨一个page只显示一张或两张图片,家里WiFi也难用,于是发挥"程序猿"的本色,写个小脚本,把图片扒 ...

  2. Hibernate学习---第十一节:Hibernate之数据抓取策略&批量抓取

    1.hibernate 也可以通过标准的 SQL 进行查询 (1).将SQL查询写在 java 代码中 /** * 查询所有 */ @Test public void testQuery(){ // ...

  3. Python3简单爬虫抓取网页图片

    现在网上有很多python2写的爬虫抓取网页图片的实例,但不适用新手(新手都使用python3环境,不兼容python2), 所以我用Python3的语法写了一个简单抓取网页图片的实例,希望能够帮助到 ...

  4. 使用IDM批量抓取音效素材下载

    IDM下载器的站点抓取功能,能够抓取网站上的图片.音频.视频.PDF.压缩包等等文件.更重要的是,能够实现批量抓取操作,省时省力.今天就来看一下,如何用IDM巧妙的批量抓取音效素材. 1.进入音效合辑 ...

  5. 抓取网页图片的脚本(javascript)

    抓取网页图片的脚本(javascript) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24172223 脚本内容 (没有换行) ...

  6. PHP抓取远程图片教程(包含不带后缀图片)

    之前做微信登录开发时候,发现微信头像图片没有后缀名,传统的图片抓取方式不奏效,需要特殊的抓取处理.所以,后来将各种情况结合起来,封装成一个类,分享出来. 创建项目 作为演示,我们在www根目录创建项目 ...

  7. php远程抓取网站图片并保存

    以前看到网上别人说写程序抓取网页图片的,感觉挺神奇,心想什么时候我自己也写一个抓取图片的方法! 刚好这两天没什么事,就参考了网上一个php抓取图片代码,重点借鉴了 匹配img标签和其src属性正则的写 ...

  8. 百度UEditor编辑器关闭抓取远程图片功能(默认开启)

    这个坑娘的功能,开始时居然不知道如何触发,以为有个按钮,点击一下触发,翻阅了文档,没有发现,然后再网络上看到原来是复制粘贴非白名单内的图片到编辑框时触发,坑娘啊............... 问题又来 ...

  9. 使用HtmlAgilityPack批量抓取网页数据

    原文:使用HtmlAgilityPack批量抓取网页数据 相关软件点击下载登录的处理.因为有些网页数据需要登陆后才能提取.这里要使用ieHTTPHeaders来提取登录时的提交信息.抓取网页  Htm ...

随机推荐

  1. iOS项目中安装和使用 Cocoapods

    1.首先我们要打开我们的终端: 2.在终端输入 这条命令  gem sources -l 2.1如果是和我是一样的显示,则镜像已添加,无需更改,如果不一样,则需要进行更改 这里输出的如果是 https ...

  2. TableViewCell,TableView,UITableViewCell

    这次的学习是在Navigation-based Application模板中,用RootViewController class设置操作方法,使用UITableView的属性值.在导航控制器控件为程序 ...

  3. 哆啦A梦 canvas

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. echarts学习网站

    echarts : http://echarts.baidu.com/echarts2/doc/example.html 相关脚本学习网站:http://www.jb51.net/html/list/ ...

  5. CSS3学习笔记1-选择器和新增属性

    前言:之前自学了一些关于CSS3的知识,在学习过程中也遇到过坑,不过总算磕磕绊绊的学习完了关于CSS3的相关知识,于是最近把之前的笔记和代码整理了一下,也算是一个对CSS3知识的回顾复习吧,也希望能够 ...

  6. CSS 定位机制 position

    position属性W3School有详细介绍 1.(position:relative;)相对定位会按照元素的原始位置对该元素进行移动.relative 2.(position:absolute;) ...

  7. PHP中类自动加载的方式

    最近在学习composer,发现从接触PHP到现在已经遇到了三种关于PHP中类的自动加载方式,这其中包括PHP自带的类的自动加载方式.PHP的第三方的依赖管理工具composer的加载方式以及PHP的 ...

  8. python之GUI编程(二)win10 64位 pygame的安装

    pygame的下载网址: http://www.pygame.org/download.shtml 我下载了第一个 很显然,安装的时候出现了如图中的尴尬,更改了安装目录后,在Python shell中 ...

  9. ORCLE基本语句(二)

    select语句的基本语法: [ORDER BY < COLUMN1, COLUMN2, COLUMN3...> [ASC 或 DESC]]

  10. spring代理模式 service远程调用,插件执行

    最近,研究了一下平台远程调用的过程,和service层插件执行的原理,记录一下. 1.远程service调用过程 首先看一下类的继承结构 封装调用处理过程 封装service调用接口 封装servic ...