python3初学应用-扒图

好久没写博客了,前段时间学了一下python语法,本着听说python很容易,然后就开始尝试学习一下这门语言,想着可以做点爬虫的东西吧。

学了语法,没应用就不好玩了。

刚好几个月前买了ukulele,爱上了这门乐器,就没事往网上搜谱子,刚好看到有个豆瓣相册很多谱子,而且还是大图清晰的,有些之前收集的,这里有清晰的,当然是直接更新过来的好,但是一百多张图片,每张都另存为多不爽,于是- -周末捣腾加上周一晚周二晚的折腾,总算是整了个相对像样的脚本成果出来了。

   先说下思路: 因为python有很好的抓数据的库,于是重点就放在了如何去 玩(fenxi)html

1.html结构分析
相册页面结构:
如果没分页就当前页面包含以下结构

<html>
   <head></head>
   <body>
	...
	<div class="photo_wrap">
		<a href=""   >
			<img src=""    />
		</a>
		<div class="pl">
			
		</div>
	</div>
	...
   </body>
   </html>


       如果有分页,则当前页面还包含一个分页的结构
	   <div class="paginator" >
			<a href="$albumPageUrl"></a>
			...
	   </div>

  文件地址分析:
路径前半部分
     http://img3.douban.com/view/photo/photo/public
后半部分为文件名  p\d*.jpg

2.程序操作逻辑设计

     1)先通过给出的url,抓取html,并分析获取到.paginator div的所有a便签子元素,将其href属性组成一个数组(分页的url)
     2)接下来就是遍历分页的url,然后就开始对url抓取html进行真正的获取图片信息,用来拼装图片的地址

     3)获取.photo_wrap 的div,获取所有的img,那么分页单页面的图片收集工作就完成了(因为谱子本身就应该有歌名对应,这个时候我加上了获取img的父标签a,其包含图片的相关描述可以用来做下载到本地后的文件名)

    4)所有的img获取完毕,遍历之,取出其src属性,并截取出文件名

    5)拼装文件名得到图片的真实路径,下载。

    完毕


3.实现支撑工具探索

python3   : python2.x跟python3.x的不兼容性,所以选取库要注意。

主要用的库是 os(文件操作),re正则, urllib.request (获取html和下载图片), beautifulsoup(分析html神器)

其中beautifulsoup是第三方库,挺不错的,要先安装才行  下面是api文档

http://www.crummy.com/software/BeautifulSoup/bs4/doc/#

    安装说明:
   需要pip管理python第三方库:安装指示线上版(要保证联网)
线下版暂时没研究
装完之后记得添加环境变量好让系统知道pip执行文件在哪里
$PythonInstallPath\Scripts


4.编码

   噼里啪啦


#python
#
#获取相册页面,分析获取分页的url
#根据抓取的url分别做处理:将url页面中的真实图片名称获取
#将上一步的名称替换到指定的图片地址格式中,开始下载图片
#
import re
import os
import urllib.request
from bs4 import BeautifulSoup
def getSoup(str_doc):
    '''根据传入的html文本生成soup对象'''
    soup = BeautifulSoup(str_doc,from_encoding='gbk')
    return soup
def getHtml(url):
    '''根据url获取html文本'''
    html = urllib.request.urlopen(url).read()
    return html
def filterForFileName(string):
    #\/?*<>:"| can't be filename in windows
    # \n \r may be avoided
    #http:... is not useful
    string = string.strip()
    regex = r"http:.*"
    string = re.sub(regex, "", string) #因为看到有些描述还加了网址的东西影响文件名命名过滤掉了
    string = string.replace('\n','').replace('\r','')
    return fileNameFilter(string)
def fileNameFilter(string):
    #windows下命名的禁止字符
    string = string.replace('/','').replace('*','').replace('?','').replace('<','').replace('>','').replace('\\','').replace('|','').replace(':','').replace('"','')
    return string
def pullImage(img_unit_list,direct):
    '''img_unit img对象'''
    direct = filterForFileName(direct)
    os.mkdir(direct)#根据direct生成目录,还没加是否已存在目录的判断
    x=0#计数用
    #大图是.../photo/large/...
    #小图是.../phtoo/photo/...
    #主要是有些相册是没大图的
    #img_1_str = "http://img3.douban.com/view/photo/large/public/"
    img_1_str = "http://img3.douban.com/view/photo/photo/public/"
    img_3_str = ".jpg"
    for img_unit in img_unit_list:
        img_src = img_unit.img_src
        slash_index = img_src.rfind('/')
        point_index = img_src.rfind('.')
        img_name = img_src[slash_index+1:point_index]
        img_url = img_1_str + img_name + img_3_str
        img_file_name = filterForFileName(img_unit.img_name)
        #下面是抓取第一个参数imgurl的文件,并以第二个参数命名文件
        urllib.request.urlretrieve(img_url,direct+'/%s-'%x +img_file_name+'.jpg')
        x+=1
    print("总共%s张图片"%x)
   
class imgunit(object):
    #存图片的路径和描述 -- 临时想到的映射方式
    img_src=''
    img_name=''
    def __init__(self,imgObj,aObj):
        #print(imgObj['src'])
        self.img_src = imgObj['src']
        self.img_name = aObj['title']
       
#first_page_url = "http://www.douban.com/photos/album/85320662/?start=0"
#"http://www.douban.com/photos/album/85320662/"
#first_page_url = 'http://www.douban.com/photos/album/85320662/'
#替换下列链接即可:相册链接
first_page_url = 'http://www.douban.com/photos/album/41149992/?start=0'
album_html=getHtml(first_page_url)
album_soup = getSoup(album_html)
#分页的链接
album_pages_url = []
album_pages_url.append(first_page_url)
#用作目录名
directory = album_soup.find('title').get_text()
#获取paginator id的div内容获取所有的a标签的 href
if album_soup.find('div','paginator')!=None:
    albums_a = album_soup.find('div','paginator').find_all("a")
    for page_a in albums_a:
        album_pages_url.append(page_a['href'])
        #print(album_pages_url)
        #由于取的是翻页部分的代码,因此需要将由于后页多余的一页的元素给移除
    album_pages_url.pop()
#存储 图片相关数据
img_units = []
for page_url in album_pages_url:
    print(page_url)
    page_html = getHtml(page_url)
    page_soup = getSoup(page_html)
    img_wrap_divs = page_soup.find_all('div','photo_wrap')
    y=0
    for img_wrap_div in img_wrap_divs:
        y+=1
        #print(y)
        img_units.append(imgunit(img_wrap_div.find('img'),img_wrap_div.find('a')))
print(len(img_units))
pullImage(img_units, directory)
   
   



5.调试

  主要出现的问题:

粗心的写错变量的无视;//多加注意

缩进严谨,调试的时候多加注意;

1)windows下文件名不能有\/?:|<>等字符,而获取的描述有http:...或者甚至有\n\r都需要做处理

待解决问题:

1)获取下载图片时中间网络不好,终止了下载,应该做好异常处理,比如记录没成功下载的图片链接而不影响后面图片的下载

2)其实豆瓣的api有提供关于相册的所有图片的信息,如果加以利用,也就不用分析那么多html标签的东西了

3)思考是否能做到更加方便点,只要提供链接即刻下载


6.修改并运行


7.感想

知识如果不运用,学了也是白学,就如看了一个月的python,结果还是各种google一下语法的问题,好在有做一些笔记。

另外就是要多学会看文档,更多的是学会更快的融入理解文档的内容!

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页