资源描述
计算机科学与工程学院
课程设计报告
题目全称: 搜索引擎之网络蜘蛛
题目难度级别: 4
指引教师: 职称:
学生姓名: 学号: 班号:
设计过程(30分)
课程设计报告(30分)
课程设计程序(40分)
总分
备注:如参加答辩,请指引教师只给出设计过程30分,课程设计报告、课程设计程序由答辩教师给出。
如参加答辩,请答辩教师签字:
指引教师评语:
指引教师签字:
搜索引擎之网络蜘蛛
1、设计背景与目:
随着网络迅速发展,万维网成为大量信息载体,如何有效地提取并运用这些信息成为一种巨大挑战。搜索引擎(Search Engine),例如老式通用搜索引擎AltaVista,Yahoo!和Google等,作为一种辅助人们检索信息工具成为顾客访问万维网入口和指南。
但是,这些通用性搜索引擎也存在着一定局限性,如:
(1) 不同领域、不同背景顾客往往具备不同检索目和需求,通用搜索引擎所返回成果包括大量顾客不关怀网页。
(2)通用搜索引擎目的是尽量大网络覆盖率,有限搜索引擎服务器资源与无限网络数据资源之间矛盾将进一步加深。
(3)万维网数据形式丰富和网络技术不断发展,图片、数据库、音频、视频多媒体等不同数据大量浮现,通用搜索引擎往往对这些信息含量密集且具备一定构造数据无能为力,不能较好地发现和获取。
(4)通用搜索引擎大多提供基于核心字检索,难以支持依照语义信息提出查询。
为理解决上述问题,网络爬虫应运而生。
网络蜘蛛(Web spider)也叫网络爬虫(Web crawler)[1],蚂蚁(ant),自动检索工具(automatic indexer),或者(在FOAF软件概念中)网络疾走(WEB scutter),是一种“自动化浏览网络”程序,或者说是一种网络机器人。它们被广泛用于互联网搜索引擎或其她类似网站,以获取或更新这些网站内容和检索方式。它们可以自动采集所有其可以访问到页面内容,以供搜索引擎做进一步解决(分检整顿下载页面),而使得顾客能更快检索到她们需要信息。
2、设计原理:
网络爬虫始于一张被称作种子统一资源地址(URLs)列表。当网络爬虫访问这些统一资源定位器时,它们会甄别出页面上所有超链接,并将它们写入一张"待访列表",即所谓"爬行疆域"(crawl frontier)。此疆域上统一资源地址将被按照一套方略循环访问。如果爬虫在她执行过程中复制归档和保存网站上信息,这些档案普通储存,使她们可以被查看。阅读和浏览她们网站上实时更新信息,并保存为网站“快照”。大容量体积意味着网络爬虫只能在给定期间内下载有限数量网页,因此要优先考虑其下载。高变化率意味着网页也许已经被更新或者删除。某些被服务器端软件生成URLs(统一资源定位符)也使得网络爬虫很难避免检索到重复内容。
基于目的数据模式爬虫针对是网页上数据,所抓取数据普通要符合一定模式,或者可以转化或映射为目的数据模式。
3、设计内容:
通过winsocket编程,读取指定网页信息。然后采用广度优先算法搜索该网页上面链接地址(搜索深度不超过3),将网页数据标题和正文内容及网址存储到文献中。
详细功能描述:
使用python3语言编写网络爬虫,建立图形界面,输入目的链接地址以及存储地址以及搜索深度(不超过3),执行搜索访问,并扩展至该链接上其她链接,通过简朴筛选将正文内容和标题存储在文献中。
支持以及几种操作:
链接框:输入初始链接
途径框:输入存储途径
途径选取:在计算机中选取存储文献(爬下来资料)放置位置
深度选取:选取深度在1~3范畴内搜索
执行搜索:点击后执行爬操作
停止搜索:点击后停止爬操作并返回截止当前成果
清空按钮:点击后清空途径、链接、以及状态栏
状态栏:即时反馈当前搜索状态
弹框:当正常结束搜索或点击停止结束搜索时弹出,返回已爬网页数目以及所用总时间
4、设计环境:
操作系统:windows 8.1
程序设计语言:Python3.4
Tkinter(图形界面)
5、设计环节:
一方面,安装Python3并学习基本用法。
使用Python3因素:Python是一种面向对象、直译式计算机程序语言,具备近二十年发展历史。它包括了一组功能完备原则库,可以轻松完毕诸多常用任务。
Python为咱们提供了非常完善基本代码库,覆盖了网络、文献、GUI、数据库、文本等大量内容,被形象地称作“内置电池(batteries included)”。用Python开发,许多功能不必从零编写,直接使用现成即可。
但有两个缺陷:
第一种缺陷就是运营速度慢,和C程序相比非常慢,由于Python是解释型语言,你代码在执行时会一行一行地翻译成CPU能理解机器码,这个翻译过程非常耗时,因此很慢。
第二个缺陷就是代码不能加密。
但是对于课程设计来说本着学习目,可以忽视这两个缺陷所带来影响。
接下来,学会基于网络爬虫和python3宽度优先搜索以及队列简朴使用:
伪代码如下:
queue Q队列
set S集合
StartPoint = "
Q.push(StartPoint) 将起点加入队列
S.insert(StartPoint) 将起点加入集合
while (Q.empty() == false) 当队列非空时
T = Q.top() 获取队首元素并且弹出
for point in T: 对于元素内所用url链接point
if (point not in S)如果该链接不在集合内(则表达没有访问过)
Q.push(point) 将point加入队列
S.insert(point) 将point加入集合
固然,在上述伪代码中没有考虑深度控制,这个非常简朴,只需要加几句话就够了。
为了实现上述伪代码,一方面是要实现链接抓取,这个py3中已有较好实现模版了:
#encoding:UTF-8
#编码方式
import urllib.request
#类似于C++语言中声明头文献
url = " "
data = urllib.request.urlopen(url).read()
#获取链接
data = data.decode('UTF-8')
#解码,输出
print(data)
输出如下:
输出中有着大量冗余代码,而需要仅仅只有标题、文本、和链接。
于是需要使用类似于字符串匹配功能,还好py3中有着字符串匹配神器:正则表达式。花了半天时间学习了正则表达式使用以及HTML语言基本规则。(由于需要使用正则表达式去筛选基于HTML语言文本)
书写了基于HTML筛选简朴正则表达式:
抓取标题:re.findall(r'<title>([\s\S]*?)</title>',data)
抓取正文:re.findall(r'>(.+?)<',data)
以及对正文筛选:
if re.match(r'.*?[{}|&<>]',正文内容):
continue
if re.match(r'[\S]*?',正文内容) and len(正文内容) > 1:
print(正文内容,file = f)
抓取链接:re.findall(r'href=["\'](.+?)["\']',data)
再接下来,抓取其她网页过程中,发既有些合法网页会浮现解码错误状况。查阅资料发现不同网站有不同编码,于是选用4种较为常用编码方式,并用py3try来实现:
try:
data = data.decode('utf-8')
except:
try:
data = data.decode('gbk')
except:
try:
data = data.decode('gb2312')
except:
try:
data = data.decode('ISO-8859-1')
except:
#print(END,"Decode error!\n")
然后,咱们需要把抓下来数据所有写入文献,又花了一定期间学习了py3中文献简朴读写,以及操作文献和目录基本用法。
学习一下几种基本操作:
import os
获取当前文献位置:pos = sys.path[0]
清除某个文献夹内容:
def delete_it(pos):#用于清空目录
for root,dirs,files in os.walk(pos,topdown=False):
for name in files:
os.remove(os.path.join(root,name))
for name in dirs:
os.rmdir(os.path.join(root,name))
判断途径与否合法: os.path.exists(pos)
途径相加: os.path.join(pos,"dirname")
原则化途径格式: os.path.normpath(pos)
文献输出流打开与关闭
f = open(pos,'w',encoding="utf-8")
f.close()
另一种办法:
with open(pos,'w',encoding="utf-8") as f:
…
当前已经完毕了链接抓取,文献存储办法,用正则表达式对网页内容进行简朴筛选和分析,那么咱们当前再使用宽度优先搜索和队列以及堆(集合)等数据构造和算法来实现整体功能。
# -*- coding:utf-8 -*-
__author__='acerlawson___Hongji_Li___'
__update_time__='-07-11 09:15:53'
queue = deque()
#队列
visited = set()
#集合,用于判断与否已经访问过
url = ""
#设立初始链接
pos = sys.path[0]
#设立初始存储位置
depth = 3
#设立深度
useless=['css','png','jpg',';','gif','ico']
#对爬虫无用链接后缀,用于筛选对于咱们无用链接,节约时间,避免程序做多了冗余运算而导致运营时间增长。
cnt = 0
#计数器,用于记录链接个数
queue.append((url,depth))
#加入初始链接到队列
visited |= {url}
#加入初始链接到集合
while queue:
url,depth = queue.popleft()
#弹出队列
try:
data= urllib.request.urlopen(url,timeout = 3).read()
#尝试获取数据
except:
#print('Failed!')
#失败或者超时
continue
try:
data = data.decode('utf-8')
except:
try:
data = data.decode('gbk')
except:
try:
data = data.decode('gb2312')
except:
try:
data = data.decode('ISO-8859-1')
except:
#print(END,"Decode error!\n")
#将解码错误url放在一起
continue
#尝试各个惯用类型解码方式
cnt = cnt + 1
#计数器+1
with open(os.path.normpath(os.path.join(pos,str(cnt)+'.txt'))
,'w',encoding="utf-8") as f:
#打开文献写入数据
print('抓取第',cnt,'个:',url,file = f)
#记录抓取序号
for s in re.findall(r'<title>([\s\S]*?)</title>',data):
#在这里咱们找出了所有<title>(………)</title>满足这种字符子串括号内容,并将其写入到文献中去。
print("Title:",s,file=f)
#写入title
for s in re.findall(r'>(.+?)<',data):
#正则表达式筛选
#在这里咱们找出了所有…>(………)<…满足这种字符子串括号内容,并准备进行下一步筛选。
if re.match(r'.*?[{}|&<>]',s):
#在这里咱们去掉所有字符子串中包括了{}|&<>等非正文惯用符号信息
continue
#正则表达式过滤1
if re.match(r'[\S]*?',s) and len(s) > 1:
#在这里咱们去掉所有字符子串中空串,以及单个字符所信息。进行接单过滤
print(s,file = f)
#正则表达式过滤2
#筛选并写入内容
#print(cnt,'get!')
#抓取成功记录到his中
show.insert(END,str(cnt)+' ok!'+'\n')
show.update()
#抓取成功!
if depth > 1:#如果剩余深度>1则扩展
for s in re.findall(r'href=["\'](.+?)["\']',data):#对于所有外链url
#在这里咱们抓取是所有href=……内容
l = len(s)#获取长度
flag =0
for t in useless:
if re.match('.*?'+t,s):
#如果抓取链接是图片或者脚本格式等之类链接,咱们将其筛掉
flag=1
break
if flag == 1:
continue
if not re.match(r'.*?http.*?',s):#补充url
s = url + s
#有也许是同一目录下链接,咱们将其进行补充根目录
if s in visited:
continue
#与否访问过 是则跳过
visited |= {s}
#加入集合
queue.append((s,depth-1))
#加入队列
endtime = time.clock()
#时间函数记录搜索过程中所总共使用时间
#printf('All finished!\nwith totals:%d\nwith time:%.1f s'%(cnt,endtime - begtime))
爬虫基本功能已经实现了,当前咱们加上一定图形化界面,在这里咱们使用Tkinter图形化界面。TkInter是原则Python GUI库。Python与Tkinter结合提供了一种迅速和容易办法来创立GUI应用程序。 Tkinter提供了一种强大面向对象接口TkGUI工具包.
使用Tkinter创立一种GUI应用程序是一件容易事。所有你需要做是执行如下环节:
导入Tkinter模块.
创立GUI应用程序主窗口.
添加上述部件之一或更多GUI应用程序.
进入主事件循环由顾客触发每个事件响应.
依照Tkinter自身提供工具,咱们只需要简朴添加几句话就可以实现简朴图形化界面了。
from tkinter import *
import tkinter.messagebox as messagebox
from tkinter.filedialog import askdirectory
#类似于调用头文献之类作用
root = Tk()
#声明一种图形化界面
root.title('小呀小爬虫 v2.2.3 ')
#设立标题
a=StringVar()
urlname = Message(root,textvariable=a)
a.set("链接地址")
urlname.pack()
#图形界面文字阐明设立
urlinput = Entry(root,width=80)
#设立宽度为80
urlinput.pack()
#链接窗口安附在界面上
b=StringVar()
posname = Message(root,textvariable=b)
b.set("存储地址")
posname.pack()
#同上作用,上次是链接,这次是存储
posinput = Entry(root,width=80)
#设立宽度为80
posinput.pack()
#地址窗口安附在界面上
pathbutton=Button(root,text='Path...',command=set_dir,width=30)
#设立功能(调用set_dir)和附件宽度
pathbutton.pack()
#触发按钮安附在界面上
c=StringVar()
depname = Message(root,textvariable=c)
c.set("深度")
depname.pack()
#图形界面上关于深度标注文字阐明
w = Spinbox(root,from_=1,to=3,width=5)
#定义取值范畴以及附件宽度大小
w.delete(0,END)
w.insert(END,2)
#初始化为2
w['state']='readonly'
#设立为只能通过按钮来变化而不能通过键盘
w.pack()
#将附件安附在界面上去
workbutton=Button(root,text='Search!',command=work,width=30)
#设立搜索按钮,名字叫Search!,触发后调用work函数,附件宽度为30
workbutton.pack()
#将搜索按钮安附在界面上去
stopbutton=Button(root,text=' Stop!',command=stop,state='disable',width=30)
#设立停止按钮,名字叫Stop!,触发后调用stop函数,初始时候不可用,附件宽度为30
stopbutton.pack()
#将停止按钮安附在附件上去
clearbutton=Button(root,text='Clear!',command=clear_it,width=30)
#设立清空按钮,名字交Clear!,触发后调用clear函数,附件宽度为30
clearbutton.pack()
#将状况按钮安附在界面上去
show = Text(root,width=100)
#设立状态栏,用于实时返回程序运营状态,附件宽度为100
show.pack()
#将状态栏安附在界面上去
root.mainloop()
这样,图形化也有了,咱们只需要将写好程序封装成各个函数,然后互相调用,协调关系,就能很简朴写出基本所有功能了。
版本更新记录:
########Ver 1.0
#1.添加了文字解说
#2.保持状态栏在更新时在底部
#3.优化了筛选正则表达式
#4.修复了某些bug
#5.增强了程序健壮性
########Ver 1.1
#1.添加了停止功能
#2.添加了途径选取功能
########Ver 1.2
#1.添加了自动删除历史功能
#2.添加了清晰状态框功能
#######Ver 1.3
#1.优化了界面
#2.提高了程序健壮性
#ver 1.3阐明:正在爬时候按除了stop以外自动 提示错误
#######Ver 2.0
#1.修复了stopbug
#2.增长了阐明(正常结束输出'all finished',stop结束输出'not finished')
#3.增长灰色按钮,取消了避免了按键不合理状况发生
######Ver 2.1
#1.修了途径选取时点取消时自动清空bug
#2.互换了 消息弹出 和 编码记录 顺序
######Ver 2.2
#1.修复了界面放大bug,虽然让界面变丑了,但是健壮性增强了。。
#2.增长了深度设立功能
######Ver 2.2.2
#1.修复了错误途径导致混乱bug
#2.修复了上次修复bug中产生bug。。
######Ver 2.2.3
#1.修复了搜索时深度未锁定bug
6、设计成果与展示:
一方面是对 学校主页进行了深度为3爬行,使用版本为2.2(详细状况看版本更新历史简介)。花了大概一种小时,爬了4500各种网页链接。
成果如图:
以及当前最新版本使用状况:
途径选取:
爬到一半暂停,返回Not finish!
爬到完所有返回All finished!
7、设计感想与总结:
通过本次课程设计,从基本目的定型到实践开发这三、四天过程,收获还是巨大。
一方面感谢指引教师耐心指引、解答在开发过程中遇到困惑与问题,并且在完毕之后还给我提供了某些合理新功能思路,使得程序一步一步得到了完善。
另一方面是对一门新语言和新事物认知和掌握。在没有任何实践经验状况下(也就是除了这学期计算机网络在理论上学习了一点),通过课程设计,我花了较短时间学习了Python3和实战了计算机网络编程。固然这和Py3语言特点也是脱不了关系。除了一门新语言简朴掌握以及计算机网络编程简朴实现,还锻炼了个人学习以及动手能力。以及通过教师和网络协助,达到了“提出问题-分析问题-解决问题”解决途径。
过去始终觉得网络爬虫是某些需要复杂算法或者对计算机底层原理有很高规定东西,通过本次网络爬虫选题,让我重新审视了网络爬虫存在。门槛可高可低,深度可深可浅。例如除了我这样简朴实现以外,还可以去伪装成浏览器去爬某些反爬虫网站等等。
总之,让我结识到了计算机网络编程精彩与美妙。
展开阅读全文