爬虫:爬取百度图片

详细过程参考下面的网址,真的很不错的文章:
https://blog.youkuaiyun.com/mingzhiqing/article/details/82778954

下面附上上面博客的代码的详细注释,我有每一步去详细注释,很容易理解:

#爬取图片就3步,1.获取图片的大图网页, 2.以二进制方式存储, 3.file.write(大图网页.content)

from urllib.parse import urlencode
import requests
import re
import os
save_dir='./baidutu/'
 
def get_page(offset):
    #这下面headers中Query String Parameters中的键值对
    params = {
        'tn': 'resultjson_com',
        'ipn': 'rj',
        'ct':'201326592',
        'is':'',
        'fp': 'result',
        'queryWord': '帅哥',
        'cl': '2',
        'lm': '-1',
        'ie': 'utf-8',
        'oe': 'utf-8',
        'adpicid':'',
        'st': '-1',
        'z':'',
        'ic': '0',
        'word': '帅哥',
        's':'',
        'se':'',
        'tab':'',
        'width':'',
        'height':'',
        'face': '0',
        'istype': '2',
        'qc':'',
        'nc': '1',
        'fr':'',
        'expermode':'',
        'cg': 'girl',
        'pn': offset*30,  #pn的值是30的倍数
        'rn': '30',
        'gsm': '1e',
        '1537355234668':'',
    }
    url = 'https://image.baidu.com/search/acjson?' + urlencode(params)
    try:
        response = requests.get(url)
        if response.status_code == 200:  #status_code是状态码,等于200就表明服务器已成功处理了请求
            return response.json()
    except requests.ConnectionError as e:
        print('Error', e.args)
        
def  baidtu_uncomplie(url):
    res = ''
    c = ['_z2C$q', '_z&e3B', 'AzdH3F']  #这几个字符串是objURL中的部分
    d= {'w':'a', 'k':'b', 'v':'c', '1':'d', 'j':'e', 'u':'f', '2':'g', 'i':'h', 't':'i', '3':'j', 'h':'k', 's':'l', '4':'m', 'g':'n', '5':'o', 'r':'p', 'q':'q', '6':'r', 'f':'s', 'p':'t', '7':'u', 'e':'v', 'o':'w', '8':'1', 'd':'2', 'n':'3', '9':'4', 'c':'5', 'm':'6', '0':'7', 'b':'8', 'l':'9', 'a':'0', '_z2C$q':':', '_z&e3B':'.', 'AzdH3F':'/'}
    if(url==None or 'http' in url):
        return url
    else:
        j= url
        for m in c:
            j=j.replace(m,d[m])
        for char in j:
            # re.match("itcast","itcast.cn”) # match 第一个参数是需要匹配的字符串,第二个是源字符串
            #[]表示匹配[]中列举的字符,^是字符串开始位置,\d表示匹配数字即0-9,$是字符串结束位置,+匹配前一个字符出现1次或者无限次,即至少有1次
            if re.match('^[a-w\d]+$',char):  #匹配是否有对应的字符
                char = d[char]  #再去d中匹配对应的键值对的值
            res= res+char  #拼接起来  
        return res
    
def get_images(json):
    #get是取字典中键值对的值,这个函数取的所有值都是preview中的键
    if json.get('data'):  #若data的值不为空
        for item in json.get('data'):  #json.get('data')得到data下面的0到30所对应的所有字典,item是0到30中的一个
            if item.get('fromPageTitle'):  #如果页面标题不为空,即你要找的关键词不为空
                title = item.get('fromPageTitle')  #获取页面标题的值
            else:
                title='noTitle'
            image = baidtu_uncomplie(item.get('objURL'))  #调用解码函数,将加密的大图网址传给解码函数,得到解码后的网址
            if(image):
                #使用一个yield的时候,对应的函数就是一个生成器了。生成器的功能就是在yield的区域进行迭代处理
                #yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值
                yield {
                    'image': image,
                    'title': title
                }

def save_image(item,count):
    try:
        response = requests.get(item.get('image'))  #item.get('image')得到图片的网址,requests.get是获取网页
        if response.status_code == 200:    ##status_code是状态码,等于200就表明服务器已成功处理了请求
            #format是格式化函数,{0}代表format中的第一个参数,即str(count),{1}代表第二个参数,即jpg
            file_path = save_dir+'{0}.{1}'.format(str(count), 'jpg')  
            if not os.path.exists(file_path):  #os.path.exists()就是判断括号里的文件是否存在的意思,括号内的可以是文件路径
                with open(file_path, 'wb') as f:  
                    f.write(response.content) 
            else:
                print('Already Downloaded', file_path)
    except requests.ConnectionError:
        print('Failed to Save Image')

def main(pageIndex,count):
    json = get_page(pageIndex)   #在这调用了get_page,获取json
    for image in get_images(json):  #在这调用了get_images,这里的image是{'image': image,'title': title}这种形式
        save_image(image, count)  #在这调用了save_image,count是数字,用来做图片名字的
        count += 1
    return count
if __name__=='__main__':
    if not os.path.exists(save_dir):
        os.mkdir(save_dir)
    count=1
    for i in range(1,20): #一次30张图,取20次,就取了600张
        count=main(i,count)
    print('total:',count)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值