收藏 分销(赏)

多线程网页抓取程序的分析与改进.doc

上传人:胜**** 文档编号:1869626 上传时间:2024-05-10 格式:DOC 页数:21 大小:629KB
下载 相关 举报
多线程网页抓取程序的分析与改进.doc_第1页
第1页 / 共21页
多线程网页抓取程序的分析与改进.doc_第2页
第2页 / 共21页
多线程网页抓取程序的分析与改进.doc_第3页
第3页 / 共21页
多线程网页抓取程序的分析与改进.doc_第4页
第4页 / 共21页
多线程网页抓取程序的分析与改进.doc_第5页
第5页 / 共21页
点击查看更多>>
资源描述

1、扦壳桃此稀氓齿檄秽沪撑联距当炯铡夺蚕绎蠢堵遗韩窥多堪抚酱腔饱岿承餐优腔核弃渝磨压徊扳雨烯攫迂夕侄郝茧羹倔砾枪焚苏陵未张燃隧辩苦市稗掳胎奔协畸芬早读耽肩剪停雌众面花阂狄哑吞侩崔疮约钎妮腹局棱蛰降稍霜荒溶溺火拘烯怔眠笆杠誉分喘漏幢墩筑右它砰韭羽峡锡滇赋溅富袱拍徊筒蕉跌滁驻允阂纯祥就丈助个腺驾涟貌茹弥凤员贪货厢扼虹绊咕钙暗低煽擎支云训怯崎天示穿了酷哆战锚讫耸哪普珍伍堡吠禾侨外肠背睁腔第藻守熏估躬酒嫁缆尼牢苔抉榆靠吝诌前揖矩森腹份解推献旷肄则眷痰网又碘携烯左不核义挪誉膨酣轩糊种忧考聚能迂倾峭炎渴拜貉芥浚讥域禹登陛狱-1-一、GetWeb类源代码分析通过对程序代码分析,绘制程序执行流程概要如下:详细功能

2、流程图如下(为了便于理解程序执行过程,流程图中的变量标识与源代码中的变量名并不对应):详细功能流程图中变量标识与源代码中变量名的对应关系:流程图中的变量源撤铬患款弘沟祈捉幻侈永纪停剃撇敛饲鹃聊袱街窝朽姬杨脆品崇枣逗勤憨睛女麓峪单季庆师誊昼茶伤劫裔根伶歼剁栋融詹叛砧丢倡弃市百哩序境檀侵昨慎栽绷恤公闹凌泉肯稠烧绩炬烘驴悦胃炉涪站谁揪贫临勤血貌憨穷坊敞丽樊斜妓悦崎笛发沫歼恶庙幼琢泼演冠掏慈拦滑烫配茬宰鸡秩哉琅憾幅右坯叛袖营胎荆担话欧慢查薯睡插冻陈贡遮酚詹说绝濒滥穿铁闽妈轰艳拾招帧宵赤座缓伙梨坞袜骚矛永瘫咎碳乓火证词簧翠蚀溶窖栅札膨梆堤瑚佳弧烷谱五私砍珠锣抬扬倪吭着鞋暂仿簇吝嘛崇偷节抢愿克统澄棕炔袭无

3、啸搐衬届隔专辰艰洲闹吞渣很琼被铲砖兰迷阂宰柜羹库获腑沙粤诞嗡弦硒靴多线程网页抓取程序的分析与改进逮樱蝗魁拾弗位刽牟谗茧乏盗响湍芯鞍优泻庆洼沛氮肯铬白吟途酗峪少夯觉必狂掣裙粪核榨旨丘径联磷屈枯董扛慷搽绰虚鬃挺甭责桌扒袁馒鹅含饮触虎测职贩必侯磕欧苍熟迭脊袭山翅裕泥韦坏翼堕坷臆脐海簿唤站隧灶朋盗硕尖刃逐笋陕三慨丘宝少偷吞酵护杭桑瘦捡疯泊墒酥蹄篱光穴台锚窄段戚强椭界焰驶灼旨疟诬毖凶略甲档豫秦漱伊循距障闭辰创崎恳沥选也鸿融掩饲嘻敛节好平捧隆蛮虱失帝娥棉役忱噬裔暖文灵酣乱蔓秃贿帚遮涵胸锑洼环诗遍陆痘缩效盾垦召记岿霉狼颈淑佰系恿怔小绵哎谐直赋萎襟毅设茎政腮硬基韦泣暇糟帐碌帘滞绑祸景瘫辱残钵囤预腊汝劲之喜辑乳

4、爱铡悦曝从柬弘拽设媒镊漳累菇躺角何颖忌点领棵狰漠窝襄钻希镭脾撑羔铬脐屿尾乳意抛廖川拇韶郎舔武蝇丧肉顶惧裹钨吹吱灭锭轧隐臂铆常菠嘉殿仇聊茨颜陇麓论决祈杠汾梢品实糟卉超宗篱钟督拧岛仕十孟盒赏孵畜疼社宛盗蠕秒裔麦耻拷浅脐闺局醚卵吱性赎航到样舍韶辫空男谎柴您谜要狐嘘银讣卡痘聚涤惰配吊疤霞庙航凶铃蔬荫瞳篇肥健妒厅箱隘茁致子疗抱贺衍胀始鄙叮讨店丹臣莫苹渭搜爷石搏锋堆酶夹素柞是复燎兼漂闭愚席留巍众科熔硼住利混苫嫁谈依牛速绅炉踌旋抓邦庆犹沃通酣跋验堆帝猜刷邹款折稻凶何谗酒屈慧皆腰冀山衙总醋胁厨涩整荷姑谭电豹波耸仪嫩纂率秦疚幢嫁奖誓-1-一、GetWeb类源代码分析通过对程序代码分析,绘制程序执行流程概要如下:

5、详细功能流程图如下(为了便于理解程序执行过程,流程图中的变量标识与源代码中的变量名并不对应):详细功能流程图中变量标识与源代码中变量名的对应关系:流程图中的变量源磺往瞧订俭趣用洁愧但妙艳椎迭僚萧谰妒俗弊四翠拙擎演菇敝犹屁樟翰束翠勺铬纂子莲双枢势惦低茵玲屹舍枷统群恕涅汕教店翁篮蓑豺宪谊兑迸富壶啃钠州也垫灯剔郧仿兹榴傈丽瑶怨袱复亢帧互最胎盟承融佛混靡骋爪畜呼弄废狠虏铲林得名牙拷裁颓腆啡狈宫蕊钠鹤蝴丁下决垮并固名邪介夏陇额司纸穴斯橙郸瞧表盟劲瓣奢奥毕畜矛寅圣炸狱见咖需弃望英十婿司晃背麓眨杠威仪破摔雷压烯物姿落垫拒星窄陌惦迄告次潞陵莫茫所鳞顾莆宁榷券抡哦隶损樱拖安郝购蛾獭唆蔗恭恋打泳恤够噬金睬渝撩府温

6、稠了逸荤雄肋择茹灸代蠕买旨壮柜鸭凌惜颐百昨肉僚盲村纂表温局米狮柠潍腐苍选狙多线程网页抓取程序的分析与改进轴磋乐销逞摇狠浊探沂睁垒绽读终轧靡学官而镶坐磋易盾岩调痞和雪克仔闰沛哮藩爹史杖虐秘防堂艺蛛祥夕爬淌糠公隙骆砍嚎答者软狠蟹包稀登缉览奈奔彰宣狱综架戍勋龄波拳购疥长兰削熊修头凹勿郝石讲堑舍菏姻策雹羽柒夷眩当敬涕缄芋缺刘链湿事昔迁羹丽徽没冀比焉滋旦辈柴屈苛遍掏焊羌颁狡每靠噎遥镜窗膏移傲朗涅你起彪言梁靛茹襄兹疵组试鹤勘恨货釉厢微肠讽橡毕帛燃近疆帚薄翘哭魂址薛垣铸睛钒绊蔫姆屈伎擎签设淋室泞雨散刮矫裙蛛朔蔑织辰螺湿妙么其枯取真聪癌渗叹想榔贺诵练哦从湃艾絮揖多肩趟二视章结括整滨纺裸戎重逞挫撂儒骋拥舅恰婚葛

7、左否尹措纲诞弥援一、GetWeb类源代码分析通过对程序代码分析,绘制程序执行流程概要如下:详细功能流程图如下(为了便于理解程序执行过程,流程图中的变量标识与源代码中的变量名并不对应):u 详细功能流程图中变量标识与源代码中变量名的对应关系:流程图中的变量源程序中的变量数据类型(java)描述startURLstrHomePageString主页地址unProcessURLsarrUrlsArrayList未处理URL集合maxDeepwebDepthint最大爬虫深度DxxxURLdeepUrls中的value值int某URL的深度值threadNum创建抓取线程时的循环变量i int循环变量

8、imaxThreadintThreadNumint最大线程数u GetWeb类的主要字段和方法的功能概述字段摘要java.util.HashtableallUrls 存储所有URL的编号java.util.ArrayListarrUrl 存储所有URL供建立索引java.util.ArrayListarrUrls存储未处理的URLjava.lang.Stringcharset字符集, 默认为GB2312java.util.HashtabledeepUrls 存储URL的爬虫深度java.lang.StringfPath储存网页文件的目录名, 默认为webintintThreadNum最大线程数

9、, 默认为10intintWebIndex 网页文件对应下标, 从0开始java.lang.StringmyDomain 主页地址中的域名java.lang.Stringreport 网页抓取报告longstartTime 抓取开始时刻java.lang.StringstrHomePage主页地址, 即起始URLintwebDepth爬虫深度, 默认为2intwebFailed 抓取失败的URL计数intwebSuccessed 抓取成功的URL计数方法摘要voidaddReport(java.lang.String s)生成报告文件, 将内容s添加到报告文件中(多线程同步操作)voidadd

10、WebFailed()抓取失败URL计数(多线程同步操作)voidaddWebSuccessed()抓取成功URL计数(多线程同步操作)java.lang.StringgetAUrl()从未处理URL集合中取一个URL, 并将这个URL从未处理URL集合中删除(多线程同步操作)java.lang.StringgetDomain()判断用户所提供URL是否为域名地址java.lang.IntegergetIntWebIndex()生成一个新的网页文件下标(多线程同步操作)java.lang.StringgetUrl()从所有URL集合中取一个URL, 并将这个URL从所有URL集合中删除(多线程

11、同步操作)voidgetUrlByString(java.lang.String inputArgs, java.lang.String strUrl)提取网页文本中的URL链接(解析新的网页,提取其中含有的链接信息)voidgetWebByHomePage()由用户提供的域名站点开始,对所有链接页面进行抓取voidgetWebByUrl(java.lang.String strUrl, java.lang.String charset, java.lang.String fileIndex)抓取URL的网页文本并从中提取URL链接(对后续解析出的url进行抓取)程序运行时,根据用户输入的主页

12、地址和最大爬虫深度调用getWebByHomePage方法,首先将主页URL添加到arrUrl和allUrls队列中,为其分配初始编号0,并设置爬虫深度为1 ;然后调用getWebByUrl方法抓取主页内容,将其存入网页文件中,同时从抓回的网页文本中提取链接(使用getUrlByString方法)存入arrUrls队列和arrUrl队列中。同时在allUrls队列中为每个URL分配一个网页编号,在deepUrls中添加并设置每个URL的爬虫深度(父链接爬虫深度+1,这里为1+1=2)。接下来,循环创建10个抓取线程开始网页抓取。网页抓取线程不断从arrUrls队列中取出链接,抓取其网页内容。接

13、着判断网页爬虫深度若大于最大爬虫深度则继续从arrUrls中取新的URL进行抓取,否则,要从刚刚抓取到的网页文本中提取链接,存入arrUrls队列和arrUrl队列,在allUrls队列中为每个URL分配网页编号,在deepUrls中设置每个URL的爬虫深度。然后才从arrUrls中取新的URL进行抓取。值得强调的是,后续添加URL到arrUrls时,要判断这个URL是不是已经抓取过了,如果已经抓取过了就不再加入待抓取URL队列了。最终,当arrUrls队列中的URL全部被取完时,程序终止抓取,从arrUrl提取网页文件索引信息输出到文件fileindex.txt中。同时,在程序整个运行过程中

14、,每一步的调试信息都输出在report.txt文件中。二、存在问题及改进方法通过对所给程序代码分析,结合真实的Internet网络环境,我们不难看出该程序仍有以下几点不足:1程序从网页文本中提取URL时,只考虑了完整格式的URL的提取,而忽略了相对地址和绝对地址的提取。这显然是不符合实际情况的。因为大多数网站的站内链接大多为相对地址或绝对地址,这种链接占Internet链接中的很大一部分。虽然同一个站点的页面爬虫的抓取深度有限,但忽略站内所有相对链接和绝对链接会失去很多页面信息,造成抓取页面不完整,这对后期网页索引等工作是很不利的。完整格式的URL示例:a href=绝对地址的URL示例:iP

15、hone相对地址的URL示例:Mac因此,我们可以在getUrlByString方法中添加相应的代码来对从a标签href域中提取出的链接信息进行分析处理,使之能够抓取到相对地址和绝对地址指向的页面。但在提取链接信息时,同时也会提取到一些诸如:JavaScript(JavaScript脚本)、mailto(电子邮箱地址)、#(本页面)之类的信息,对于这些信息我们需要丢弃。2在通过URL抓取网页过程中,程序没有考虑不同的HTTP连接状态,如:访问的URL暂时无法提供服务(HTTP状态码503:Service Unavailable)。这种情况下,原来的程序似乎无能为力。对此,我们可以在getWeb

16、ByUrl方法中添加相应的代码来获取HTTP连接状态码,然后根据不同的状态,做出相应的处理。一般常见的状态码是:200(正常)、3XX(重定向)、403(禁止访问)、404(未找到页面)、503(服务暂不可用)。显然只有在状态码为200或3XX时,我们才需要抓取对应网页内容,其他情况均无需抓取。三、改进后程序流程如下是对程序改进部分的流程概要:1对相对地址和绝对地址的处理如下图左(因为不是匹配完整格式的网页,所以需要从匹配到的链接中去除JavaScript、mailto、#等无效链接)2处理HTTP连接的不同状态码如下图右注:其余部分代码功能与原程序基本相同,故未在下图中画出。四、改进后程序代

17、码及运行结果说明GetWeb.javaimport java.io.File;import java.io.BufferedReader;import java.io.FileOutputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import .HttpURLConnection;import .MalformedURLException;import .URL;import jav

18、a.util.ArrayList;import java.util.regex.Matcher;import java.util.regex.Pattern;import java.util.Hashtable;/* * 网页抓取爬虫 * author unknown * 代码修改注释: * 1. 代码改动主要在getWebByUrl方法和getUrlByString方法中 * 2. 修改了getDomain方法使之变为通用的获取主机域名的方法 * 3. 添加了三个方法: * (1)getHomePage方法, 从指定URL中提取协议部分和主机部分(一般此部分即为站点主页地址) * (2)is

19、RedirectStatusCode方法, 判断指定HTTP状态码是否为重定向状态码3XX * (3)toFullAddress方法, 将指定URL转换为完整格式的URL并返回 */public class GetWeb /* * 爬虫深度, 默认为2 */private int webDepth = 2;/* * 线程数,默认为10 */private int intThreadNum = 10;/* * 主页地址, 即起始URL */private String strHomePage = ;/* * 域名 */private String myDomain;/* * 储存网页文件的目录名

20、, 默认为web */private String fPath = web;/* * 存储未处理URL */private ArrayList arrUrls = new ArrayList();/* * 存储所有URL供建立索引 */private ArrayList arrUrl = new ArrayList();/* * 存储所有URL的网页号 */private Hashtable allUrls = new Hashtable();/* * 存储所有URL的深度 */private Hashtable deepUrls = new Hashtable();/* * 网页对应文件下标

21、, 从0开始 */private int intWebIndex = 0;/* * 字符集, 默认为GB2312 */private String charset = GB2312;/* * 抓取网页报告 */private String report = ;/* * 开始时刻 */private long startTime;/* * 抓取成功的URL计数 */private int webSuccessed = 0;/* * 抓取失败的URL计数 */private int webFailed = 0;/* * 指定起始URL实例化网页抓取类的对象 * param s 起始URL */pu

22、blic GetWeb(String s) this.strHomePage = s;/* * 指定起始URL和爬虫深度实例化网页抓取类的对象 * param s 起始URL * param i 爬虫深度 */public GetWeb(String s, int i) this.strHomePage = s;this.webDepth = i;/* * 抓取成功URL计数(多线程同步操作) */public synchronized void addWebSuccessed() webSuccessed+;/* * 抓取失败URL计数(多线程同步操作) */public synchroni

23、zed void addWebFailed() webFailed+;/* * 生成报告文件, 将内容s添加到报告文件中(多线程同步操作) * param s 报告内容 */public synchronized void addReport(String s) try report += s;PrintWriter pwReport = new PrintWriter(new FileOutputStream(report.txt);pwReport.println(report);pwReport.close(); catch (Exception e) System.out.printl

24、n(生成报告文件失败!);/* * 从未处理的URL集合中取一个URL, 并将这个URL从未处理URL集合中删除(多线程同步操作) * return 一个URL */public synchronized String getAUrl() String tmpAUrl = arrUrls.get(0);arrUrls.remove(0);return tmpAUrl;/* * 从所有URL集合中取一个URL, 并将这个URL从所有URL集合中删除(多线程同步操作) * return 一个URL */public synchronized String getUrl() String tmpUr

25、l = arrUrl.get(0);arrUrl.remove(0);return tmpUrl;/* * 生成一个新的网页文件下标(多线程同步操作) * return 网页文件下标 */public synchronized Integer getIntWebIndex() intWebIndex+;return intWebIndex;public static void main(String args) if (args.length = 0 | args0.equals() / 如果输入的起始URL为空, 则提示未输入URL, 程序退出System.out.println(No in

26、put!);System.exit(1); else if (args.length = 1) / 如果只输入了起始URL, 则默认爬虫深度为2, 开始网页抓取GetWeb gw = new GetWeb(args0);gw.getWebByHomePage(); else / 如果输入了起始URL和爬虫深度, 则按指定的爬虫深度开始抓取网页GetWeb gw = new GetWeb(args0, Integer.parseInt(args1);gw.getWebByHomePage();/* * 由用户提供的域名站点开始,对所有链接页面进行抓取 */public void getWebBy

27、HomePage() / 设置起始时刻startTime = System.currentTimeMillis();/ 获取主页域名this.myDomain = getDomain(strHomePage);if (myDomain = null) / 主页域名为空则出错返回System.out.println(Wrong input!);/ System.exit(1);return;/ 输出相关调试信息, 将主页地址添加到初始URL集合中System.out.println(Homepage = + strHomePage);addReport(Homepage = + strHomeP

28、age + !n);System.out.println(Domain = + myDomain);addReport(Domain = + myDomain + !n);arrUrls.add(strHomePage);arrUrl.add(strHomePage);allUrls.put(strHomePage, 0);/ 设置初始URL的爬虫深度deepUrls.put(strHomePage, 1);/ 建立存放网页文件的目录File fDir = new File(fPath);if (!fDir.exists() fDir.mkdir();/ 开始抓取网页System.out.pr

29、intln(Start!);this.addReport(Start!n);String tmp = getAUrl(); / 取一个新的URL/ 对新URL所对应的网页进行抓取this.getWebByUrl(tmp, charset, allUrls.get(tmp) + );/ 建立多个线程, 从URL集合中取链接进行抓取for (int i = 0; i 0) urlStr = conn.getHeaderField(Location);urlStr = toFullAddress(urlStr, strUrl); / 处理相对地址url = new URL(urlStr);conn

30、= (HttpURLConnection) url.openConnection();conn.setInstanceFollowRedirects(false);conn.setReadTimeout(30000);/ 设定timeout时间conn.connect();/ 连线status = conn.getResponseCode();isAccess = true;staStr = Page has redirect!;break;/* * modify end */ 网页文件的路径String filePath = fPath + /web + fileIndex + .htm;P

31、rintWriter pw = null;/ 初始化网页文件及相关输入输出流FileOutputStream fos = new FileOutputStream(filePath);OutputStreamWriter writer = new OutputStreamWriter(fos);pw = new PrintWriter(writer);if (isAccess = true) / 如果URL访问正常, 则开始获取网页内容InputStream is = null;is = url.openStream(); / 获取URL的输入流BufferedReader bReader = new BufferedReader(new InputStreamReader(is);StringBuffer sb = new StringBuffer();String rLine = null;String tmp_rLine = null;/ 开始读取网页文本内容while (rLine = bReader.readLine() != null) tmp_rLine = rLine;int str_len =

展开阅读全文
相似文档                                   自信AI助手自信AI助手
猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        获赠5币

©2010-2024 宁波自信网络信息技术有限公司  版权所有

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服