Python批量下载新浪微博相册

最近用Python写了一个新浪微博相册的批量下载程序,选好用户后运行就可以把他相册的全部相片下载到本地。记录了下载历史,可以中途停止和续传。

新浪微博浏览相册需要登录,在尝试了模拟登录之后,在登录机制和验证码上纠结了很久,最后我选择了直接用cookie登录,这样其实更省事。

Python2.7,应该就用了requests这个第三方库,API用起来更舒服。

pip install requests

使用的时候:
1.先打开该用户的微博页面,F12或者查看源代码,找到他的page_id,填到程序的uid处。
2.用F12或者其他监听软件找到cookies,填入程序cookies处。
3.把希望保存的本地目录路径填入程序中dirpath处。

下面是完整代码

# coding=u8
#作者:平仄_pingze (简书)

"功能"
'''
获取新浪微博用户相册照片到本地
'''

"使用方法"
'''
1.填写储存目录
2.指定微博用户id
3.填写cookie
4.运行
'''

# ---|| 初始参数,需要预先填写 ||---
dirpath = ''  #储存目录
uid =   #用户page_id
cookies = ''  #cookies


import os
import requests
import urllib
import re
from StringIO import StringIO
import pickle
import traceback
import time


def list_find(alist,ele):
    '不报错的list.index()'
    try:
        return alist.index(ele)
    except:
        return -1

def get_response(url,headers='',params=''):
    '稳定高效的获取响应方法'
    max_try_times = 20 # 最大尝试次数
    wait_time = 0.75 # 最大单次尝试时间
    sleep_time = 0.25 # 尝试失败延时
    #print('[%s][INFO] Start trying to connect ...' % time.asctime()[11:19])
    for times in range(1,max_try_times+1):
        # print('[%s][INFO] The %s time try begin ...' % (time.asctime()[11:19], times))
        try:
            response = requests.get(url, timeout = wait_time, headers=headers, params=params)
            # print('[%s][INFO] The %s time try success!' % (time.asctime()[11:19], times))
            break
        except:
            if times < max_try_times:
                # print('[%s][WARN] The %s time try failed!' % (time.asctime()[11:19], times))
                time.sleep(sleep_time)
                continue
            else:
                print('[%s][ERROR] The last try failed at last , exit pro ...' % time.asctime()[11:19])
                traceback.print_exc()
                exit()
    # print('[%s][INFO] Successfully get the response!' % time.asctime()[11:19])
    return response

def retrieve(imgurl,imgpath):
    '稳定高效的下载图片方法(多次尝试失败后跳过)'
    max_try_times = 5 # 最大尝试次数
    wait_time = 15 # 最大单次尝试时间
    sleep_time = 3 # 尝试失败延时
    import socket
    socket.setdefaulttimeout(wait_time)
    #print('[%s][INFO] Start trying to connect ...' % time.asctime()[11:19])
    for times in range(1,max_try_times+1):
        # print('[%s][INFO] The %s time try begin ...' % (time.asctime()[11:19], times))
        try:
            urllib.urlretrieve(imgurl,imgpath)
            # print('[%s][INFO] The %s time try success!' % (time.asctime()[11:19], times))
            break
        except:
            if times < max_try_times:
                # print('[%s][WARN] The %s time try failed!' % (time.asctime()[11:19], times))
                time.sleep(sleep_time)
                continue
            else:
                print('[%s][ERROR] The last try failed at last , pass ...' % time.asctime()[11:19])
                break
    # print('[%s][INFO] Successfully get the response!' % time.asctime()[11:19])

def secp(string,pattern1,pattern2=''):
    '替换字符串中所有指定字符串为新字符串(效率低)'
    while True:
        index = string.find(pattern1)
        if index > -1:
            string = string[:index]+pattern2+string[index+len(pattern1):]
        else:
            break
    return string

def url_deal(url):
    'URL处理'
    urld = secp(url,'\\')
    urld = secp(urld,'thumb300','large')
    return urld

def get_imgurl(html):
    '解析html,获取图像url列表'
    imgurl_list = []
    extlist = ['jpg','gif','png']
    for ext in extlist:
        pattern = r'class=\\\"photo_pict\\\" src=\\\"(http:\S+thumb300\S+.'+ext+')'
        result = re.findall(pattern,html,re.S)
        if len(result) > 0:
            for url in result:
                imgurl_list.append(url_deal(url))    
    return imgurl_list  

def save_img(imgurl,savepath,imgname):
    '向本地目录储存图像'
    imgext = imgurl[-4:]
    imgname = imgname + imgext 
    retrieve(imgurl,savepath+os.sep+imgname)

def save_log(dic, path):
    '以pickle文件格式储存到目标路径'
    try:
        out_file = open(path, 'wb')
        pickle.dump(dic,out_file)
        return path
    except:
        traceback.print_exc()
        return None
    finally:
        out_file.close()     

def load_log(path):
    '从指定文件读取pickle文件转成字典'
    try:
        in_file = open(path, 'rb')
        dic = pickle.load(in_file)
        return dic
    except:
        traceback.print_exc()
        return None

def main():
    url = 'http://www.weibo.com/p/'+str(uid)+'/photos'
    headers = {
        'Cookie': cookies
    }
    #访问网址,获取html文档
    response = get_response(url, headers=headers)
    print('[%s][INFO] Pro starting at %s ...' % (time.asctime()[11:19], response.url))
    html = response.text
    #检查html是否有效;若无效,报错并中止
    if len(re.findall('thumb300',html,re.S)) < 1 and len(re.findall('oid',html,re.S)) < 1 and len(re.findall('的微薄',re.S)) < 1:
        print('[%s][ERROR] Invalid cookies or page_id, please check !' % (time.asctime()[11:19]))
        exit()
    #解析文档,获取用户信息和图片路径
    uname = re.findall(u'content="(.+?),',html,re.S)[0]
    imgurl_list = get_imgurl(html)
    #动态获取循环
    while True:
        #获取since_id,进一步获取动态加载的页面
        result = re.findall('since_id=(\S+)">',html,re.S)
        if len(result)>0:
            since_id = result[0][:-1]
        else:
            break
        #print(since_id)
        payload={
            'since_id': since_id,
            'page_id': uid,
            'ajax_call': 1
        }
        url = 'http://weibo.com/p/aj/album/loading'
        response = get_response(url,params=payload,headers=headers)
        html = response.text
        print('[%s][INFO] Got new page of %s !' % (time.asctime()[11:19], response.url))
        #解析文档,获取html路径
        imgurl_list = imgurl_list + get_imgurl(html)
    savepath = dirpath + os.sep + uname
    if(os.path.exists(savepath)==False or os.path.isdir(savepath)==False):
        os.mkdir(savepath)
    imgurl_list.reverse()
    global total_num
    total_num = len(imgurl_list)
    #log文件存在性检查
    logpath = savepath + os.sep + 'log.pkl'
    if os.path.exists(logpath) and os.path.isfile(logpath):
        print('[%s][INFO] Found log.pkl, loading...' % (time.asctime()[11:19]))
        logdic = load_log(logpath)
        log_last_num = logdic.get('last_num')
        log_imgurl_list = logdic.get('imgurl_list')
        index = log_last_num + 1
    else:
        print('[%s][INFO] Not found log.pkl, creating a new one ...' % (time.asctime()[11:19]))
        log_imgurl_list = []
        index = 1
    #开始下载图片
    num = 1
    for imgurl in imgurl_list:
        if list_find(log_imgurl_list, imgurl) < 0: 
            imgname = '{:0>5}'.format(index)
            save_img(imgurl, savepath, imgname)
            index = index + 1
            last_num = index - 1
            log_imgurl_list.append(imgurl)
            logdic = {
                'last_num': last_num,
                'imgurl_list': log_imgurl_list
            }
            print('[%s][INFO] Writing log ... (%d/%d) !' % (time.asctime()[11:19], num, total_num))
            save_log(logdic, logpath)
            print('[%s][INFO] Successfully saved image as %s (%d/%d) !' % (time.asctime()[11:19], imgname, num, total_num))
        else:
            print('[%s][INFO] Jump this image (%d/%d) !' % (time.asctime()[11:19], num, total_num))
        num = num + 1

if __name__ == '__main__':
    main()

比如我的初始参数是:

dirpath = 'images' #与脚本同目录的images文件夹
uid = 1035051191258123 # 韩寒
cookies = 'SINAGLOBAL=221.237.83.131_146556……' #很长,不给你看

套路是这么个套路,大家有什么想法可以提一提嘛……

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,039评论 25 707
  • 首先详细说明一下什么是cookies? 当用户通过浏览器首次访问一个域名时,访问的WEB服务器会给客户端发送数据,...
    是蓝先生阅读 1,249评论 1 6
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,089评论 4 62
  • 死亡,是永恒的主题。在苏童的笔下,死亡少了那份孤独与绝望,多了份宿命与奇异。 读过他几篇短篇,里面的人物结局都...
    玛贝拉阅读 1,020评论 0 1
  • 日子过得乱七八糟。尤其是这次返校。 和茜坐在公园里,偷片刻的欢愉。当然,大学生了,又是周末,有大把时光造作,用“偷...
    咕噜不爱弹吉他阅读 310评论 1 0