您的位置:首页技术文章
文章详情页

python制作微博图片爬取工具

【字号: 日期:2022-06-29 16:42:33浏览:2作者:猪猪

有小半个月没有发博客了,因为一直在研究python的GUI,买了一本书学习了一些基础,用我所学做了我的第一款GUI——微博图片爬取工具。本软件源代码已经放在了博客中,另外软件已经打包好上传到网盘中以供下载学习。

一.准备工作

本次要用到以下依赖库:re json os random tkinter threading requests PIL 其中后两个需要安装后使用

二.预览1.启动

python制作微博图片爬取工具

2.运行中

python制作微博图片爬取工具

3.结果

这里只将拿一张图片作为展示。

python制作微博图片爬取工具

三.设计流程

设计流程分为总体设计和详细设计,这里我会使用viso画出几个流程图,用以展示我的思路,其中详细设计部分,我列举了两个函数实现的具体流程。

1.总体设计

python制作微博图片爬取工具

此图为整个系统的整体流程也是本GUI软件的使用过程。

2.详细设计

在此列举两个函数一个是搜索按钮触发的wb_search函数,一个是开始爬取按钮触发的wb_pics_parse函数。

2.1wb_search函数

python制作微博图片爬取工具

2.2wb_pics_parse函数

python制作微博图片爬取工具

四.源代码

import jsonimport randomimport reimport osfrom tkinter import *from tkinter import messageboxfrom tkinter import ttkimport requestsimport threadingfrom PIL import Image,ImageTk'''1.07使用check button 实现下载完打开文件夹操作,注册了enter、esc热键,优化了一些体验1.08 1.更新了关键字、磁盘、用户判断逻辑 2.将之前的线程池改为多线程来执行下载操作1.13说明:如果在下载过程变慢,可能是软件正在解析图片地址或者就是您的网络不行'''class WeiBo_pics_Spider(object): def __init__(self,start_url): self.start_url=start_url #解析出图片地址 def get_pics_url(self): i = 1 global a_flag a_flag = True while True: url = self.start_url + ’&page={}’.format(i) headers = {’User-Agent’: get_ua()} r = requests.get(url, headers=headers) _json = json.loads(r.text) items = _json['data']['cards'] flag = _json[’ok’] if flag == 1 and a_flag: # 爬取数据标志+一个手动控制标志for v in items: picslist = v.get(’mblog’) if picslist is not None: img_urls = picslist.get(’pics’) if img_urls != None: for img_url_ in img_urls:img_url = img_url_[’large’][’url’]yield img_url else:#1.06页数显示出现问题t1.insert(END, f’***在第{i}页终止***n’)t1.see(END)t1.update()if r1_var.get() == 1: big_dir=disk+’:/WeiBo_Pics’ os.startfile(big_dir)break i += 1 #下载图片 def download_pics(self,url,filename): headers={’User-Agent’: get_ua()} r = requests.get(url, headers=headers) big_dir=disk+’:/WeiBo_Pics’ aim_path=big_dir+’/’+user_name_selected try: os.makedirs(aim_path) except: pass with open(aim_path + ’’ + filename, ’wb’)as f: f.write(r.content) # 保证焦点始终在最下 t1.see(END) # 下载完一张刷新一次 防止界面卡死崩溃 t1.insert(END, f’{filename}n’) window.update()def get_ua(): first_num = random.randint(55, 62) third_num = random.randint(0, 3200) fourth_num = random.randint(0, 140) os_type = [ ’(Windows NT 6.1; WOW64)’, ’(Windows NT 10.0; WOW64)’, ’(X11; Linux x86_64)’, ’(Macintosh; Intel Mac OS X 10_12_6)’ ] chrome_version = ’Chrome/{}.0.{}.{}’.format(first_num, third_num, fourth_num) ua = ’ ’.join([’Mozilla/5.0’, random.choice(os_type), ’AppleWebKit/537.36’, ’(KHTML, like Gecko)’, chrome_version, ’Safari/537.36’] ) return uadef wb_search(): #先清空lsibox1内容,便于新内容显示 listb1.delete(0,END) url1=’https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D3%26q%3D{}%26t%3D0’ headers={’User-Agent’:get_ua()} key_word = e1.get() global user_id_list user_id_list=list() if len(key_word)!=0: #若用户输入了user_id,则去获取screen_name if re.match(’d{10}’,key_word): user_id_list.append(key_word) url2 = f’https://m.weibo.cn/api/container/getIndex?uid={key_word}&containerid=100505{key_word}’ r1 = requests.get(url2, headers=headers) _data = json.loads(r1.text) screen_name = _data[’data’][’userInfo’].get(’screen_name’) l3.place(x=120, y=42) l3_var.set(f’搜索成功’) l3[’background’] = ’green’ listb1.insert(END, screen_name) #否则根据关键字去搜索用户信息,显示在listbox中 else: aim_url=url1.format(key_word) r=requests.get(aim_url,headers=headers) _json=json.loads(r.text) try:#若出现了IndexError则表明没有检索到用户信息users=_json[’data’][’cards’][1].get(’card_group’)relevant_num=len(users)l3.place(x=105, y=42)l3_var.set(f’搜索到了 {relevant_num} 个用户’)l3[’background’]=’green’for user_ in users: user_info=user_.get(’user’) user_name=user_info.get(’screen_name’) id = user_info.get(’id’) ''' 1.02的一种思路,使用一个列表存储screen_name和uid,两者用;(自定义字符,但应避免较少冲突) 当获取Uid时,直接切割字符串,取Listbox所选项索引,按索引在列表表值(uid) #使用字符串拼接 格式:screen_name+’;’+str(id) # user_data = user_name + ’;’ + str(id) ''' user_id_list.append(id) listb1.insert(END,user_name) except IndexError:#如果没有检索到用户,就会报列表索引错误messagebox.showinfo(title=’提示’, message=’没有检索到相关用户,请更换关键字或使用用户id搜索!’)l3.place(x=85, y=42)l3_var.set(f’请更换关键字或用户id搜索!’)l3[’background’]=’yellow’#没有检索到用户的话,提示之后,e1获得焦点之后,清除用户之前输入e1.bind(’WM_TAKE_FOCUS’, e1_clear()) else:#处理没有输入关键字 messagebox.showinfo(title=’info’,message=’请输入关键字!’) l3.place(x=110, y=42) l3_var.set(f’请输入关键字!’) l3[’background’] = ’red’def wb_pics_parse(): key_word=e1.get() select_path=c1.get() #1.先判断关键字是否输入 if len(key_word)!=0: #2.再判断是否选择了磁盘 if len(select_path)==1: #3.判断所选路径是否存在 if not os.path.exists(select_path):#4.判断是否在列表框选择了用户名try: # 直接获取选中项目 '''1.05获取Listbox user_name_selected真费劲''' global user_name_selected user_name_selected=listb1.get(listb1.curselection()) user_name_index = listb1.curselection()[0] user_id = user_id_list[user_name_index] container_id = ’107603’ + str(user_id) start_url = f’https://m.weibo.cn/api/container/getIndex?containerid={container_id}’ spider = WeiBo_pics_Spider(start_url) t1.config(state=’normal’) # 将Text开启,置为可读可写状态 l3.place(x=120, y=42) l3_var.set(f’正在运行......’) l3[’background’] = ’green’ for pic_url in spider.get_pics_url(): filename = pic_url.split(’/’)[-1] # 字符串切割,切割出前10个字符串 filename = filename[10:] thread_it(spider.download_pics,pic_url,filename)#搜索后,但是没选择用户,会报TclError错误,此except就用来捕获这个异常except TclError: messagebox.showwarning(title=’警告’, message=’请选择一个用户!’) l3.place(x=105, y=42) l3_var.set(f’请选择一个用户!’) l3[’background’] = ’red’#获取当前选中项目(使用索引) else:messagebox.showwarning(title=’警告’,message=’请检查路径!’)l3.place(x=80, y=42)l3_var.set(f’请检查路径!’)l3[’background’] = ’red’ else: messagebox.showwarning(title=’警告’, message=’您未选择磁盘!’) l3.place(x=85, y=42) l3_var.set(f’请检查是否选择了磁盘!’) l3[’background’] = ’red’ else: messagebox.showwarning(title=’警告’, message=’请输入关键字!’) l3.place(x=110, y=42) l3_var.set(f’请输入关键字!’) l3[’background’] = ’red’def open_disk(): disk=c1.get() big_dir=disk+’:/WeiBo_Pics’ if len(disk)==1: try: if not os.path.exists(big_dir):os.mkdir(big_dir) os.startfile(big_dir) except: messagebox.showwarning(title=’警告’,message=’选中的磁盘不存在!’) l3.place(x=110, y=42) l3_var.set(f’选中的磁盘不存在!’) l3[’background’] = ’red’ else: messagebox.showwarning(title=’警告’, message=’您未选中磁盘!’) l3.place(x=115, y=42) l3_var.set(f’您未选中磁盘!’) l3[’background’] = ’red’def window_quit(): ret=messagebox.askyesno(title=’提示’,message=’是否要退出?’) if ret==True: window.destroy() window.quit()def e1_clear(): e1.delete(0,END)def print_path(event): #要使用完整的路径 global disk disk = c1.get() disk_path=c1.get()+’:/’ if len(disk)==1: if os.path.exists(disk_path): messagebox.showinfo(title=’提示’,message=f’文件将存储到:{disk}:/WeiBo_Pics目录下’) else: messagebox.showerror(title=’错误’,message=’选定磁盘不存在!’) l3.place(x=100, y=42) l3_var.set(f’选中的磁盘不存在!’) l3[’background’] = ’red’ else: messagebox.showwarning(title=’警告’, message=’请先选定磁盘!’) l3.place(x=120, y=42) l3_var.set(f’请先选定磁盘!’) l3[’background’] = ’red’def switch(): if r1_var.get()==0: r1_var.set(1) else: r1_var.set(0)def escape(event): window_quit()def enter(event): wb_search()’’’解决程序卡死的重要方法,避免子线程和Ui线程在同一个线程’’’def thread_it(func, *args): ’’’将函数打包进线程’’’ # 创建 t = threading.Thread(target=func, args=args) # 守护 !!! t.setDaemon(True) # 启动 t.start() # 阻塞--卡死界面! # t.join()window=Tk()width=310height=395screenWidth = window.winfo_screenwidth() # 获取显示区域的宽度screenHeight = window.winfo_screenheight() # 获取显示区域的高度left = (screenWidth - width) / 2top = (screenHeight - height) / 2window.geometry('%dx%d+%d+%d' % (width, height, left, top))window.resizable(0,0)window.title(’微博图片采集工具-v1.08’)#设置图标ico_path=r’./rely/icon.ico’window.iconbitmap(ico_path)#插入图片到Label中photo = Image.open('./rely/w_b.png') # 括号里为需要显示在图形化界面里的图片photo = photo.resize((150, 40)) # 规定图片大小img0 = ImageTk.PhotoImage(photo)l1=ttk.Label(window,imag=img0,justify=’center’)l1.pack()l3_var=StringVar()l3=ttk.Label(window,background=’yellow’,textvar=l3_var)l3.place(x=120,y=42)l3_var.set(’还没搜索’)l1=ttk.Label(window,text=’关键字或n用户id:’)l1.place(x=13,y=60)e1=ttk.Entry(window,justify=’center’)e1.place(x=80,y=65)l4=ttk.Label(window,text=’磁盘:’)l4.place(x=13,y=100)disk_list=[’C’,’D’,’E’,’F’,’G’,’H’,’I’]c1=ttk.Combobox(window,justify=’center’,state=’readonly’,width=17,value=disk_list)#Combobox默认选中索引为0的项目 即 C盘c1.bind(’<<ComboboxSelected>>’, print_path)c1.place(x=80,y=100)r1_var=IntVar()r1_var.set(1)#默认选中为1check1=Checkbutton(window,text=’下载完n打开文件夹’,command=switch)check1.place(x=223,y=90)b1=ttk.Button(window,text=’搜索’,command=lambda:thread_it(wb_search),width=7)b1.place(x=230,y=63)l5=ttk.Label(window,text=’用户列表:’)l5.place(x=13,y=150)lb1_var=StringVar()listb1=Listbox(window,justify=’center’,listvariable=lb1_var,width=20,height=4)listb1.place(x=80,y=135)b2=ttk.Button(window,text=’开始爬取’,command=lambda :thread_it(wb_pics_parse,),width=7)b2.place(x=230,y=160)l6=ttk.Label(window,text=’状态:’)l6.place(x=13,y=280)t1=Text(window,width=23,font=(’times new roman’,10),state=’disable’)t1.place(x=80,y=230,height=140)b3=ttk.Button(window,text=’ 打开n文件夹’,width=7,command=open_disk)b3.place(x=230,y=230)b3=ttk.Button(window,text=’退出’,width=7,command=window_quit)b3.place(x=230,y=315)f1 = ttk.LabelFrame(window)f1.place(x=65,y=350)l6=ttk.Label(f1,text=’敬告:本软件仅供学习交流使用!’,foreground=’red’)l6.pack(anchor='w',fill=X)#绑定esc键---退出window.bind(’<Escape>’,escape)#使用return键给输入框Entry绑定enter事件---search搜索e1.bind(’<Return>’,enter)#加入主窗口销毁事件window.protocol(’WM_DELETE_WINDOW’,window_quit)window.mainloop()五.总结说明

本软件仅供学习交流使用!图源水印,在此仅作举例!由于这是第一次做GUI,因此遇到了一些问题,在此列举一下:1.窗口布局问题(GUI基础)2.主窗口执行一个比较耗时操作导致卡死、崩溃(线程问题)。3.主窗口关闭后,后台线程还在运行(线程问题)。

以上问题已经全部解决,软件切实可用。

另外,本软件有四大亮点:

1.使用线程下载图片2.智能标签提醒3.输入关键字直接敲回车能够完成搜索4.Esc快速退出软件软件打包好了放在了蓝奏云https://wws.lanzous.com/iPSpzkchj5i

以上就是python制作微博图片爬取工具的详细内容,更多关于python 微博图片爬取的资料请关注好吧啦网其它相关文章!

标签: 微博 Python
相关文章: