Python学习记录之一爬图片

    最近在学python,一搜python搜出来很多关于爬虫的信息,大概看了一下,感觉挺有意思的,于是呢,也来学着写写,先从最简单的爬图片开始吧。搜了几个图站,都不太满意,倒不是说图片不好看,而是要么页面广告多,要么乱七八糟的各种东西,恰好这时候发现一个不健康的网站,哈哈,干脆就爬这个算了。

    先说一下这要涉及到的知识,主要就是python的两个库,requests和BeautifulSoup,还有需要简单了解一下html的知识。爬网站其实就是模仿浏览器访问网站,以我目前的粗浅理解,整个流程是这样的:
1.  调用requests.get方法给目标网站发送一个请求
2.  目标网站收到请求之后会返回一个包含有网页源码的对象
3.  从源码中找到我们需要的图片的地址
4.  用图片地址再次发送get请求,然后把收到的信息保存起来,就是图片啦

    下面分析一下将要爬的这个网站,由于是个不健康网站,不方便上图,就分析一下源码吧。这个网站首页有大概100小标题,每个小标题就是一个跳转链接,点击之后会打开一个新的网页,里面有10多张图,我的目标是把这些图片全都下载下来,那么首先需要把这些标题的链接提取出来,然后再在新页面的源码里找到图片的地址。

包含标题链接的标签

    `def get_req(url):
print url
return requests.get(url)`
def find_a_url(r): 
    all_url = []
    soup = BeautifulSoup(r.text,'lxml') 
    title = soup.find_all('a', class_ = 'T')

    for t in title:
        str = t.get('href')
        url = re.search('http:.*$',str)
        all_url.append(url.group(0))

    return all_url
    简单说一下这部分的代码。传入参数r就是requests.get 返回的包含有网页全部信息的一个对象,r.text就是经过解码之后的文本类型的网页信息,经过BeautifulSoup处理成一种特定的结构,方便bs里的方法进一步处理,然后返回这个对象。Find_all方法用于在源码中寻找满足要求的标签,并将所有满足要求的标签存在一个list里返回。然后遍历所有a标签,从里面取出bref这一段,再用正则表达式取出http部分,都存起来,至此,我们就得到了首页所有标题的网址。

    接下来,该分析跳转的子网页的源码了,这次是找图片了,应该是更好找了,毕竟图片地址看结尾的后缀很明显,然后呢,看网页可以确定这些图片大概分几个部分,主图的源码肯定是在一起的,广告的源码,还有一些其他小图片的源码肯定都是分开的。看了源码,最笨的方法,图地址一块一块的看,感觉像的放浏览器里试一下,很快就找到了。大图是在div标签下,div style="display: none",有一点不同,每一张图片都是div下的一个子标签,但是不要紧,我们有contents可以遍历出div标签的所有子标签,然后就跟前面一样了,从每一个a标签里拿出href,为了方便测试我把得到到所有图片地址都存到了一个文本里,后面下载的时候直接从文本里读,然后就出了个悲剧。。。

    子页面的标签找出来之后是这样,图片传不上来。。。
    <div style="display: none">
<a href="http://images.xxxxxx.pics/p/hot_babe_akane-ozora-sucks-coc-avidolz/avidolz_01.jpg">
    <img src="src="http://images.xxxxxx.pics/p/hot_babe_akane-ozora-sucks-coc-avidolz/avidolz_01.jpg">
</a>
def find_src(url):
    i = 0
    all_src = []
    for u in url:
        r = get_req(u)
        print i
        i += 1
        soup = BeautifulSoup(r.text,'lxml')
        title = soup.find('div', style = 'display: none')

        for child in title.contents:
            if child.name == 'a':
                src = child.get('href')
                all_src.append(src)
    return all_src

下载函数以及往文件写的函数:

def download(des_path,src_path):
    number   = 0

    if not os.path.exists(des_path):
        os.makedirs(des_path)

    with open(src_path,'r') as f:
        url = f.readlines()

    for u in url:
        filename = str(number) + r'.' + 'jpg'   
        path     = os.path.join(r'/',des_path,filename)
        u = u.strip('\n')

        with open(path,'wb') as f:
            r = requests.get(u)
            for chunk in r.iter_content(1000):
                f.write(chunk)

            print u
            print path
            print r.status_code

        number += 1

def write_to_file(file_name,src):
    with open(file_name,'w') as f:
        for s in src:
            f.write(s)
            f.write('\n')
    头和尾:
#-*- coding:utf-8 -*-
import requests
import sys
import re
import os.path
from bs4 import BeautifulSoup

reload(sys)
sys.setdefaultencoding('utf-8')

if __name__ == '__main__':
    url       = 'http://xxxxxx.pics/'
    src_path  = 'img_src.txt'
    des_path  = 'G:/python/download'
    r         = get_req(url)
    url       = find_a_url(r)
    src       = find_src(url)

    write_to_file(src_path,src)
    download(des_path,src_path)
    然后就是下载部分了,没什么特别需要强调的,就记录一下出的这个错。我从txt里读取图片地址,然后一个个的传给requests.get去访问,然后就是等着咯,由于有1500多张图片,所以程序运行还是要一定的时间的,中间也没报错,终于终于运行完了的时候,很开心,打开文件夹一看,蒙逼了,全都打不开,白特么等了,再一看,所有的图片都一样大,45个字节,这显然是哪里出错了。这时候不用想肯定是下载部分的代码有问题啊,因为从文本中读出的地址打印出来是正常的,放到浏览器里也能访问,我单个地址穿进去也能下载成功,为啥就加了个循环就不行了呢,非常想不通,怀疑是不是因为写的时候要分多次写,加了循环后有什么未知的影响导致只写了一次。又一想还是不对,就算只写一次,写的大小也是1000而不是45,那么问题就是网站返回的信息就不对。这下更想不明白了,我单独把链接复制到requests里不循环可以下载成功,就加了个循环怎么就不行了呢。然后寻思吧返回的状态码打印出来看一下,一看,返回的是400,意思是之歌网址不对,或者没权限访问,那肯定就是网址不对呗。尼玛,老子狗眼都要瞅瞎了也看不出链接有什么不同。最后写了个列表,把15个地址一个个手动复制进去,另一个列表装的是从文件里读出来的15个地址,然后同时打印出list[0],第一次没看出来,第二次感觉好像哪不对劲,然后注释掉一个,打印另一个对比,尼玛,发现了,从文本里读出来的后面有个换行符,因为我往文本里写的时候,为了好看一点,写一个链接,写一个换行符。然后赶紧找到stirng. Strip(’\n’)这个函数加上,把换行符给去掉,终于一切正常了。

    至于代码中这几个方法的用法,文档里写的很清楚,我就不多记录了,都有中文文档,直接百度就出来了,关于html的介绍,就看w3school,很详细。

    另:第一次写博客啊,昨晚都快写完了,显示发表成功,结果没发出去,又重新写了一下,主要就是记录一下自己的学习过程,方便以后查阅,新手上路,路过的大神请多多指教。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值