本文是作者为了能够熟悉tkinter以及ttkbootsrtap和简单爬虫的练习项目,并没有什么高超的水平。希望读者在看完后,留下自己宝贵的意见。
上面是需要的库
在建立窗口部分,这几个column和row我总是用不好,不是很能理解它们应该如何正确使用,我想要把说明部分全部移动到右下角,但是怎么改row都是在上一个的下面
注意:这里tkinter的页面是用tkinter.Tk()来创建一个窗口对象的,在ttk中则使用Window
这里使用messagebox中的showinfo来进行消息提示,showinfo(),前两个参数为标题和提示内容
首先是保存到本地的功能
采用追加的方式写入,同时简单的调整格式,但是依旧很丑,想要了解一下怎么处理格式的问题
上面是多页面采集,首先获取输入框(Entry)内的字符串,创建一个字典,键值对的格式为,网址+bool变量,bool用于标记该网站是否被访问过。
下面是两个循环,judge的作用是用于判断字典中是否添加了新的成员,由于字典在发生变化后,不能继续遍历,我在添加了成员后,会退出这个循环,重新进行遍历一次
然后是遍历部分,在字典中的key值中遍历,首先看该key值对应的value是否为False,如果没有被访问,那么就继续,使用urlopen中的read读取源代码信息,并标记为访问,然后使用bs4解析器进行解析,然后获取文本,使用save函数保存。
查找源代码中包含的子链接信息。首先遍历查找标签为href的数据,然后获取它内部的值,之后通过正则表达式来判断它是否以http开头,如果符合就将其添加进入字典,然后标记当前Key为已访问。
单页面采集没有什么特殊的东西,是多页面采集的简化版本
定义了一系列的按钮,并将它们和函数捆绑,定义了一个字典
定义了一个ListBox,供用户自主选择
这里最重要的获取listbox的文本,将listbox与listbox_click的函数进行绑定,使用lb.curselection来获取文本,利用delete来清空文本,以及Insert来插入文本
以上,本文结束,本人没有学习几天,代码存在这很多的缺陷,希望各位看客能够指点一二
完整代码如下:
from tkinter import *
from tkinter import messagebox
import ttkbootstrap as ttk
from bs4 import BeautifulSoup
from urllib.request import urlopen
import re
web=str()#定义一个全局变量用于存储
#建立窗口部分
window=ttk.Window()
window.title("简单的网络数据采集工具")
window.geometry("700x550+600+300")
lab_input=Label(window,text="请在下面的方框内输入要采集的网站网址",font=("宋体",12))
lab_file=Label(window,text=" 请在下方输入文件路径(包括名称)")
input_bar=Entry(window,width=20)
file_bar=Entry(window,width=20)
lab_input.grid(column=5,row=0)
lab_file.grid(column=5,row=6)
input_bar.grid(column=5,row=3)
file_bar.grid(column=5,row=7)
#消息提示部分
def inform():
messagebox.showinfo("工具介绍", "该工具可以简单的进行网络数据采集,但是对于信息的整理和分类本人并不擅长\
此工具是本人为了学习tkinter和scrapy的练习,不能保证结果正确,由于技术原因,能采集到的信息确实有限,更加倾向于采集文本信息\
(采集到其他的信息都会变成乱码(;´༎ຶД༎ຶ`) \
默认提供的几个网站都是确定可以采集到的,其他网站可以自行输入,本人不能保证有效\
由于各大网站很多有反爬虫机制,本人没有做很多的适配,故效果欠佳( •̀ ω •́ )✧ \
(小红书,微博,米游社,知乎,这些网站采集的信息很少,因为我都不会(ToT)/~~~ 推荐用海大的网站测试!! \
作者:一只蛙 2023-7-8 ")
def inform_sole():
messagebox.showinfo("两种采集说明","单个页面采集指的是仅仅解析输入的网址,不会在其子链接中跳转来继续搜集,多个页面采集会在其子链接中进行多次采集\
多页面采集的都是与主页面(即输入的网址)相关的网站,可能会无响应,但是其实还是在工作,数据够了就关掉")
def inform_save():
messagebox.showinfo("保存说明","搜集到的文本信息会保存到本地,在保存的框中需要输入待保存的路径,例如C:\\Windows\\text.txt,注意要带上文件后缀,如果不输入,默认的位置在该程序的文件夹下,默认名称为text.txt")
def finish():
messagebox.showinfo("保存","该页面的信息已成功提取完毕!")
#采集数据部分
file_name="text.txt"
def save_file(datas):
if datas==None:
return
else:
with open(file_name,"a",encoding='utf-8') as f:#使用追加的方式写入
datas=datas.split()
num=int(0)
for i in datas:#以上用于整理格式
f.write(i+' ')
num=num+1
if num%15==0:
f.write('\n')
num=num//15
def multi():
web=input_bar.get()
webs=dict()
webs[web]=False#未访问
for j in range(1,100):
try:
judge=False
for i in webs.keys():#遍历值
if webs[i]==False:#未访问
html_=urlopen(i).read()
webs[i]=True#访问标记
bsobj_=BeautifulSoup(html_,"html.parser")
datas_=bsobj_.get_text()#获取文本
save_file(datas_)
for link in bsobj_.find_all():
if 'href' in link.attrs:
url_=link.attrs['href']
match=re.match(r"http",url_)
if match:
if url_ not in webs:
webs[url_]=False#添加进去
judge=True
if judge==True:#如果增加了元素
break
except:
continue
else:
finish()
def sole():
try:
web=input_bar.get()
html=urlopen(web).read()
bsobj=BeautifulSoup(html,"html.parser")
data=bsobj.get_text()
save_file(data)
finish()
except:
return
#定义按钮
bn_intro=Button(window,text="说明&作者",width=10,command=inform)
bn_sole=Button(window,text="单个页面采集",width=10,command=sole)
bn_multi=Button(window,text="多个页面采集",width=10,command=multi)
bn_inf_sl=Button(window,text="两种采集说明",width=10,command=inform_sole)
bn_inf_sv=Button(window,text="保存说明",width=10,command=inform_save)
bn_sole.grid(column=5,row=4)
bn_multi.grid(column=5,row=5)
bn_inf_sl.grid(column=6,row=6)
bn_inf_sv.grid(column=6,row=7)
bn_intro.grid(column=6,row=8)
init_dict={"海南大学官网":"https://www.hainanu.edu.cn/"
,"CSDN":"https://www.csdn.net/"
,"网易新闻":"https://news.163.com/"
,"4399":"https://www.4399.com/"
,"百度贴吧":"https://tieba.baidu.com/"}
box=StringVar()
t_list=list()
for i in init_dict.keys():
t_list.append(i)
box.set(t_list)
lb=Listbox(window,listvariable=box)
lb.grid(column=1)
def listbox_click(event):#必须要有event!
input_bar.delete(0, END)#将开始到末尾清空
value=lb.get(lb.curselection())
url=init_dict[value]
input_bar.insert(0,url)#插入文本
lb.bind('<<ListboxSelect>>',listbox_click)
window.mainloop()