python写的百度贴吧相册下载

突然想搞个这样的工具,写来写去都不知道在干嘛了,本来两个文件,现在整合在一起了。

乱得不行,懒得整理了,能用就行。

下载部分用了多线程,但是下载一个文件还是用的单线程,也就是没管http头的range问题。貌似速度也不咋地。

开始遇到的一个问题是直接用urllib的urlretrieve或者是先urlopen再read()出来老是出错,或者丢失,后来本来打算外挂一个wget.exe来下载,想来想去还是得不偿失,所以现在分几个block来读,应该是可以的。

另外百度相册用了ajax的动态页面加载技术,所以在浏览器上看到的带#号或者#!的url不能直接用urllib去open,#后的东西是不会POST到服务器的。

后来用浏览器的审查元素工具,切换到网络页面,发现请求的url,其实还是传递了参数的,这就比较好解决了。

算了,丢代码吧。

PS:最近发现美版的《极速前进》很好看,这段时间一直在看

# -*- coding: cp936 -*-
import urllib,re,urllib2
import os,os.path
import time
import threading
import sys

IS_DEBUG = False
MULTI_THREAD = False
MAX_Thread = 20

tieba_info_fp = ""

#tbName = raw_input("输入贴吧名称:")
tbName = ""
tieba_url_base = "http://tieba.baidu.com"
pgUrl_base="http://tieba.baidu.com/photo/g?kw="
photo_url_base = "http://imgsrc.baidu.com/forum/pic/item/"

BLOCK_SIZE = 4096
threadLock = threading.Lock()

# 打印信息到文件和屏幕
def print_f(msg):
    global tieba_info_fp
    print msg
    tieba_info_fp.write(msg+‘\n‘)
    tieba_info_fp.flush() 

def download_file(url,path):
    if os.path.isfile(path):
        return
    r = urllib.urlopen(url)
    fileName = ""
    if path != "":
        fileName = path
    elif r.info().has_key(‘Content-Disposition‘):
        fileName = r.info()[‘Content-Disposition‘].split(‘filename=‘)[1]
        fileName = fileName.replace(‘"‘, ‘‘).replace("‘", "")
    else:
        fileName = url[url.rfind(‘/‘)+1:]

    if os.path.isfile(fileName):
        return
    else:
        file_length = int(r.info()[‘Content-Length‘])
        download_size=0
        f = open(fileName, ‘wb‘)
        try:
            while download_size<file_length:
                dat = r.read(BLOCK_SIZE)
                l = len(dat)
                if l>0:
                    f.write(dat)
                    download_size += l
                else:
                    f.close()
                    os.remove(fileName)
                    raise Exception,"time out"
        except Exception,e:
            f.close()
            os.remove(fileName)
            raise Exception,e
        finally:
            f.close()

class MultiDownload(threading.Thread):
    def __init__(self,dat):
        threading.Thread.__init__(self)
        self.dat = dat
    def run(self):
        while 1:
            pos,url,path = self.dat.start_one()
            if pos == None:
                break
            try:
                download_file(url,path)
                self.dat.end_one(pos)
            #出错标记为未下载
            except Exception,e:

                self.dat.renew_one(pos)
                print url,e

class DData:
    def __init__(self):
        self.pos = 0
        self.url = []
        self.path = []
        #0 1 2
        self.status = []

    def add(self,url,path):
        self.url.append(url)
        self.path.append(path)
        self.status.append(‘0‘)
        self.pos += 1

    #获取一条未下载的数据,并设置为1(正在下载),返回pos,所有都下载完返回None
    def start_one(self):
        try:
            pos = self.status.index(‘0‘)
            threadLock.acquire()
            self.status[pos] = ‘1‘
            threadLock.release()
            return pos,self.url[pos],self.path[pos]
        except ValueError:
            return None,None,None

    #结束一条下载
    def end_one(self,pos):
        threadLock.acquire()
        self.status[pos] = ‘2‘
        threadLock.release()

    #标记未下载一条下载
    def renew_one(self,pos):
        threadLock.acquire()
        self.status[pos] = ‘0‘
        threadLock.release()

def multi_download_run(url_list,path_list=[],MAX_Thread=10):
    dat = DData()
    for i in xrange(0,len(url_list)):
        if path_list==[]:
            fn = url[url.rfind(‘/‘)+1:]
            path = os.path.join(os.getcwd(),fn)
        else:
            path = path_list[i]
        dat.add(url_list[i],path)
    threads = []
    for i in xrange(0,MAX_Thread):
        threads.append(MultiDownload(dat))
    for t in threads:
        t.start()
    for t in threads:
        t.join()

def multi_download(pic_list):
    url_list = []
    path_list =[]
    for id in pic_list:
        fn = id + ".jpg"
        url = photo_url_base + fn
        path = os.path.join(os.getcwd(),fn)
        url_list.append(url)
        path_list.append(path)
    multi_download_run(url_list,path_list,MAX_Thread=10)

# 进入子目录,如果不存在则创建
def chsubdir(dirname):
    cwd=os.getcwd()
    subdir = os.path.join(cwd,dirname)
    if os.path.exists(subdir) == False:
        os.mkdir(subdir)
    os.chdir(subdir)

## 读取相册
def read_album(tid,name):
    chsubdir(name)
    if IS_DEBUG == True:
        return
    url= ‘http://tieba.baidu.com/photo/bw/picture/guide?kw=%s&tid=%s&see_lz=1&from_page=0&alt=jview&next=15‘%(tbName,tid)
    # print url
    pageData = urllib.urlopen(url).read()
    #print pageData
    p = re.compile(‘"pic_amount":(\d+),‘)
    pic_amount = p.search(pageData).group(1)
    print_f ("┗━━"+name + ‘ ‘+pic_amount + ‘张‘)
    p = re.compile(‘"original":{"id":"(\S+?)"‘)
    find_list = p.findall(pageData)
    pic_list = find_list
    i= len(pic_list)
    pic_amount=int(pic_amount) # 转化为整数型
    while pic_amount>i:
        #print i
        url2 = url+"&prev=0&pic_id="+pic_list[-1]
        pageData = urllib.urlopen(url2).read()
        p = re.compile(‘"original":{"id":"(\S+?)"‘)
        find_list = p.findall(pageData)
        pic_list = pic_list + find_list[1:]
        i=len(pic_list)
    multi_download(pic_list)

## 读取相册集
def read_catalog(url,name):
    if name != ‘‘:
        chsubdir(name)
        print_f(name)
    page = 1
    while 1:
        url_page = "%s&pn=%d"%(url,page)
        pageData = urllib2.urlopen(url_page).read()
        p = re.compile (‘<div class="grbm_ele_title.+?href="(\S+?)".+?title="(.+?)"‘,re.S)
        result = p.findall(pageData)
        root_dir = os.getcwd()
        if len(result)==0:
            break
        else :
            for a in result:
                #cUrl = tieba_url_base + a[1]
                tid=a[0][3:]
                cName = a[1]
                os.chdir(root_dir)
                read_album(tid,cName)
            page += 1

## 读取根目录信息
def read_root(url,name):
    global tieba_info_fp
    chsubdir(name)
    try:
        tieba_info_fp = file(‘%s吧信息.txt‘%(name),"w")
        print_f(‘【%s】‘%(name))
        pageData = urllib.urlopen(url).read()
    #1、读取总相片数量
        p = re.compile (‘<div class="picture_amount_total">共有图片 (\d+?) 张</div>‘,re.S)
        result = p.findall(pageData)
        picture_amount_total = 0
        if len(result) == 0:
            print_f(‘可能这个贴吧不存在,或者这个程序已经不能使用‘)
            tieba_info_fp.close()
            return
        else:
            picture_amount_total = int(result[0])
        print_f(‘共有图片 %d 张‘%(picture_amount_total))

    #2、先尝试存在相册分类的情况
        p = re.compile (‘<li class="catalog_li_normal.+?href="(\S+?)".+?catalog_a_inner">(.+?)<span class="catalog_a_amount">\((\d+?)\)</span>‘,re.S)
        result = p.findall(pageData)
        root_dir = os.getcwd()
        if len(result)>0:
            for a in result:
                cat_id = a[0][10:]
                cat_name = a[1]
                os.chdir(root_dir)
                cat_url = url+ "&cat_id=" + cat_id
                read_catalog(cat_url,cat_name)
    #3、没有相册分类,直接获取所有相册目录
        else:
            cat_url = url+ "&cat_id=all"
            read_catalog(cat_url,‘‘)
    except Exception,e:
        print e
    finally:
        tieba_info_fp.close()

def main():
    global tbName
    args = len(sys.argv)
    if args>1:
        for i in range(1,args):
            tbName = sys.argv[i]
            print sys.argv[i]
            pgUrl = pgUrl_base + tbName
            read_root(pgUrl,tbName)
    else:
        tbName = raw_input("输入贴吧名称:")
        pgUrl = pgUrl_base + tbName
        read_root(pgUrl,tbName)

if __name__ == ‘__main__‘:
    main()

  

时间: 2024-10-03 03:59:26

python写的百度贴吧相册下载的相关文章

python写的百度图片爬虫

学了一下python正则表达式,写一个百度图片爬虫玩玩. 当技术遇上心术不正的人,就成我这样的2B青年了. python3.6开发,在Windows下需要安装vc2015动态库.下载地址:http://www.cr173.com/soft/146014.html 1 #/usr/bin/env python 2 #Guoyabin 3 #-*- coding:utf-8 -*- 4 import re,os 5 import requests 6 7 keyword=input('请输入搜索关键

用python实现的百度音乐下载器-python-pyqt-改进版

之前写过一个用python实现的百度新歌榜.热歌榜下载器的博文,实现了百度新歌.热门歌曲的爬取与下载.但那个采用的是单线程,网络状况一般的情况下,扫描前100首歌的时间大概得到40来秒.而且用Pyqt做的界面,在下载的过程中进行窗口操作,会出现UI阻塞的现象. 前两天有时间调整了一下,做了几方面的改进: 1.修改了UI界面阻塞的问题,下载的过程中可以进行其它的UI操作; 2.爬虫程序采用一个主线程,8个子线程的方式快速爬取,网络状况一致的情况下,将扫描100首歌曲的时间提高到了8.9秒左右:(本

用Python写一个ftp下载脚本

用Python写一个ftp下载脚本 ----基于Red Hat Enterprise Linux Server release 6.4 (Santiago):python 2.6.6 Ps:少侠我接触Python半个月以来接到的第一个需求,虽然如此简单的一个脚本,少侠我磕磕绊绊却用了将近一天半的时间才写出来,但还是很开心,毕竟也粗来了,废话不多说,切入正题.因为一开始没有用过ftplib模块,所以各种谷歌度娘一堆资料杂乱不堪,话不清,理不乱的,本文实现的功能简单,下面介绍一下,以免误导读者. 需

用Python写一个最简单的网络爬虫

什么是网络爬虫?这是百度百科的解释: 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁,自动索引,模拟程序或者蠕虫. 爬虫可以做什么?爬虫可以帮助我们在茫茫互联网中爬取我们需要的特定数据,这个特定数据可以是任何想获得的数据. 爬虫是一个让人热血的话题,因为当你在写爬虫的时候,你会感觉到自己是在做一件很NB的事,而每当写出一个爬虫,就会在此基础上不断尝试写出更NB的爬虫,有

2018用Python写网络爬虫(视频+源码+资料)

课程目标实现Python写网络爬虫入门适用人群数据零基础爱好者,职场新人 ,在校大学生课程简介1.基本Http请求以及验证方式分析 2.Python用于处理Html格式数据beautifulsoup模块3.Pyhton的requests模块的使用并实现爬取B站.网易云.微博.内涵段子等网站4.异步IO模块的使用,如:asyncio.gevent.aiohttp.twisted.torando 5.自定义异步IO模块 6.Scrapy框架的使用以及应用 下载地址:百度网盘 原文地址:http://

用Python写网络爬虫(高清版)PDF

用Python写网络爬虫(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1kdRFAEuze-A9ToWVXHoCXw 提取码:8ib1 复制这段内容后打开百度网盘手机App,操作更方便哦 内容简介  · · · · · · 作为一种便捷地收集网上信息并从中抽取出可用信息的方式,网络爬虫技术变得越来越有用.使用Python这样的简单编程语言,你可以使用少量编程技能就可以爬取复杂的网站. <用Python写网络爬虫>作为使用Python来爬取网络数据的杰出指南,

如何Python写一个安卓APP

前言:用Python写安卓APP肯定不是最好的选择,但是肯定是一个很偷懒的选择,而且实在不想学习Java,再者,就编程而言已经会的就Python与Golang(注:Python,Golang水平都一般),那么久Google了一下Python写安卓的APP的可能性,还真行. 既然要写个APP,那么总得要有个想法吧. 其实笔者想做两个APP来着,一个是自己写着好玩的,一个是关于运维的. 关于运维的APP,设计应该如下 可能长这样 然后设计应该是这样. 如果觉得可行的话,评论留言一下你觉得应该写进这个

用python写MapReduce函数

尽管Hadoop框架是用java写的,但是Hadoop程序不限于java,可以用python.C++.ruby等.本例子中直接用python写一个MapReduce实例,而不是用Jython把python代码转化成jar文件. 例子的目的是统计输入文件的单词的词频. 输入:文本文件 输出:文本(每行包括单词和单词的词频,两者之间用'\t'隔开) 1. Python MapReduce 代码 使用python写MapReduce的"诀窍"是利用Hadoop流的API,通过STDIN(标准

下载hibenate tools插件(百度搜hibenate tools 下载)

Eclipse插件的安装和使用1.     在线更新( http://blog.csdn.net/charlies_fu/article/details/5638068)打开eclipse工具,选择HELP---Install new software----输入网址,如我们这里要安装hibernate tools进行逆向工程的建立,输入http://download.jboss.org/jbosstools/updates/development 选择hibernate tools----安装