Python:批量下载百度贴吧原图(超详细)


1. 背景

  百度贴吧上有许多美图,几张或十几张图片手动下载还可以,但几十张,上百张就比较麻烦,故希望编个程序批量下载百度贴吧的原图。由于python爬虫代码简单,故利用python来编程。

孙允珠吧

2. 准备

2.1 贴吧组成

  现在使用孙允珠吧举例。一个贴吧由一个个帖子组成,帖子中包含图片。故理论上下载原图的一般方法是:先打开贴吧主页,再打开帖子,然后点击图片使其原图显示,最后下载图片。

孙允珠吧主页
孙允珠吧帖子
孙允珠吧帖子中图片原图显示

2.2 分析网页url

贴吧主页:http://tieba.baidu.com/f?kw=%CB%EF%D4%CA%D6%E9&fr=ala0&loc=rec
贴吧帖子:http://tieba.baidu.com/p/6383722178
原图显示:http://tieba.baidu.com/photo/p?kw=%E5%AD%99%E5%85%81%E7%8F%A0&ie=utf-8&flux=1&tid=6383722178&pic_id=4254484e251f95ca67a500d0c6177f3e660952e7&pn=1&fp=2&see_lz=1
分析结果:
1. 贴吧主页中 “kw=%CB%EF%D4%CA%D6%E9” 是gb2312格式的UrlEncode编码,“kw=%E5%AD%99%E5%85%81%E7%8F%A0” 是utf-8格式的UrlEncode编码,它们解码结果是:孙允珠。
解码网站:站长工具UrlEncode编码/解码

UrlEncode解码前
UrlEncode解码后

2. 贴吧帖子中 “6383722178” 是帖子编号。
3. 原图显示中 “pic_id=4254484e251f95ca67a500d0c6177f3e660952e7” 是图片编号。
4. 由原图显示的url可知,打开1张原图需要 “kw=%E5%AD%99%E5%85%81%E7%8F%A0” 、“tid=6383722178” 和 “pic_id=4254484e251f95ca67a500d0c6177f3e660952e7”

2.3 分析关键信息

  1. 打开贴吧主页。点击右上角设置图标->更多工具->开发者工具(谷歌浏览器),或网页鼠标右键点击->检查即可看到源码。
谷歌浏览器打开源码方式
  1. Ctrl+F查找帖子编号 “6383722178” ,找到关键代码,提取出正则表达式。若提取内容不同,所需的正则表达式需要自己修改,不懂可以参考Python3 正则表达式
    注意:浏览器上看到的关键代码和程序获取的关键代码是不同的。
浏览器上帖子关键代码

程序获取的关键代码:

<li class=" j_thread_list clearfix" data-field='{&quot;id&quot;:6383722178,&quot;author_name&quot;:&quot;lovedovelyonly&quot;,&quot;author_nickname&quot;:null,&quot;author_portrait&quot;:&quot;tb.1.d0fa6477.jIFXO-fqudlDDQVl2lym9g&quot;,&quot;first_post_id&quot;:128733834249,&quot;reply_num&quot;:26,&quot;is_bakan&quot;:null,&quot;vid&quot;:&quot;&quot;,&quot;is_good&quot;:true,&quot;is_top&quot;:null,&quot;is_protal&quot;:null,&quot;is_membertop&quot;:null,&quot;is_multi_forum&quot;:null,&quot;frs_tpoint&quot;:null}'  data-tid='6383722178' data-thread-type="0" data-floor='6''>

程序所需的正则表达式:

r1 = r"data-tid='([0-9]+)' data-thread-type"  # 正则表达式
  1. 同样打开贴吧首页的1个帖子,Ctrl+F查找图片编号 “4254484e251f95ca67a500d0c6177f3e660952e7”,获取关键代码,提取出正则表达式。
浏览器上帖子关键代码

程序获取的关键代码:

<img class="BDE_Image" pic_type="0" width="560" height="560" src="http://imgsrc.baidu.com/forum/w%3D580/sign=61a7dc9d0546f21fc9345e5bc6256b31/4254484e251f95ca67a500d0c6177f3e660952e7.jpg" size="555815" >

程序所需的正则表达式:

r2 = r'src="http://imgsrc.baidu.com/(.*?)\.jpg"'  # 正则表达式
  1. 打开原图显示url的源码,找出可下载原图的地址。
原图显示的源码

可下载原图的地址:

http://imgsrc.baidu.com/forum/pic/item/4254484e251f95ca67a500d0c6177f3e660952e7.jpg

三、处理流程

  从上面的下载地址可知,下载原图需要知道 “4254484e251f95ca67a500d0c6177f3e660952e7” 即图片编号。故批量下载图片时,只需给定贴吧首页的url,由首页url的源码找出帖子编号,再由帖子编号读取帖子源码,从而获取图片编号。最后由图片编号组成原图下载地址,通过其下载图片。

流程图

四、源代码

from urllib import request  # 下载图片
import re  # 正则表达式
import os  # 创建文件夹
from tqdm import trange  # 进度条

# 读取主页源码
url1 = "http://tieba.baidu.com/f?kw=%CB%EF%D4%CA%D6%E9&fr=ala0&loc=rec"  # 贴吧首页的网址
html = request.urlopen(url1, timeout=5)  # 读取网页源码
code = html.read().decode("UTF_8")
"""
file = open("1.html", "w", encoding='UTF-8')  # 保存源码
file.write(str(code))
file.close
print(code)
"""

# 提取帖子编号
r1 = r"data-tid='([0-9]+)' data-thread-type"  # 正则表达式
c1 = re.compile(r1)  # 根据正则表达式创建模式对象
f1 = re.findall(c1, code)  # 匹配结果
# 提取帖子名称
r2 = r'href="/p/[0-9]+" title="(.*?)"'  # 正则表达式
c2 = re.compile(r2)  # 根据正则表达式创建模式对象
title = re.findall(c2, code)  # 匹配结果
i = 0
# 创建Image文件夹
if not os.path.exists("Image"):
    os.mkdir("Image")

for tid in f1:
    i = i + 1
    # 读取帖子源码
    url3 = 'http://tieba.baidu.com/p/' + tid  # 帖子地址 'http://tieba.baidu.com/p/6383722178'
    html3 = request.urlopen(url3, timeout=5)  # 读取网页源码
    code3 = html3.read().decode("UTF_8")
    # 提取图片编号
    r3 = r'src="http://imgsrc.baidu.com/(.*?)\.jpg"'  # 正则表达式
    c3 = re.compile(r3)  # 根据正则表达式创建模式对象
    f3 = re.findall(c3, code3)  # 匹配结果
    # 以该帖子的名称创建文件夹
    dir1 = "Image//" + title[i] + "(共" + str(len(f3)) + "张)//"
    if not os.path.exists(dir1):
        os.mkdir(dir1)  # 创建帖子文件夹
    with trange(len(f3)) as bar:  # 进度条
        for j in bar:
            # 下载图片并保存
            s = f3[j].split("/")
            pic_id = s[len(s) - 1]
            # 图片下载地址'http://imgsrc.baidu.com/forum/pic/item/4254484e251f95ca67a500d0c6177f3e660952e7.jpg'
            url4 = 'http://imgsrc.baidu.com/forum/pic/item/' + pic_id + '.jpg'
            f = open(dir1 + str(j) + ".jpg", 'wb')
            f.write((request.urlopen(url4, timeout=5)).read())
            f.close()
            # 打印进度信息
            bar.set_description(str(i) + ". " + title[i] + "(共" + str(len(f3)) + "张)")

print("贴吧首页下载完成。")
程序运行结果

五、遇到的问题

问题1:点击程序运行,但程序一直卡住,既不报错,又没有结果。
原因:经调试发现程序一直卡住code = html.read(),所以程序应加上超时处理和异常处理。如此程序会正常报错。
报错程序:

from urllib import request

html = urllib.request.urlopen(url)
code = html.read()
code = code.decode("UTF_8")

改正后程序

from urllib import request, error

try:
    html = request.urlopen(url, timeout=3)
    code = html.read()
    code = code.decode("UTF_8")
except error.URLError as e:
    print(e.reason)

问题2:点击程序运行,发出超时错误。
原因:这可能是网络连接不佳或者网站发现是爬虫程序而禁止访问,推荐博客python urllib.request的5个基本程序,使用异常处理,User_Agent和IP代理运行测试一下是否可以读取url的源码。

问题3:百度贴吧首页下载完成,想换页怎么办?

孙允珠吧首页
孙允珠吧第2页
孙允珠吧第10页

解决方法:由上图可知,其它页的网址可以直接从首页推出。即第n页的url
="http://tieba.baidu.com/f?kw=%E5%AD%99%E5%85%81%E7%8F%A0&ie=utf-8&pn="+(n-1)*50

问题4:在百度贴吧首页查找帖子编号 “6383722178”和图片编号 “4254484e251f95ca67a500d0c6177f3e660952e7”也能找到,为何还要打开具体帖子读取图片编号?
解答:百度贴吧首页获取的图片编号只是帖子中图片编号的一部分而已,它并不完全。

问题5:在具体帖子的源码中已经可以找到所有图片编号以及地址,为何不用这个地址,而要使用原图显示图片的地址?
解答:直接使用帖子中的图片地址也是可以下载图片的,但它只是按比例缩小的缩略图,不是原图。

六、参考资料

1、Python学习笔记(二)urllib.urlopen()超时问题 : 504Gateway Time-out
2、【Python】urllib库——下载网页、爬虫汇总

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