美文网首页
课程设计 Python 网络爬虫(广度优先方法)

课程设计 Python 网络爬虫(广度优先方法)

作者: 下载掌门人 | 来源:发表于2018-07-04 18:30 被阅读0次

    很多语言都可以实现爬虫,由于python的易用性,这里使用python.

    • 程序功能:爬取一个域名下的所有网页,并将网页之间的指向关系存储在字典中。可以通过domain 设置域名、可以通过depth设置深度。
    • 程序原理:1. 使用urllib.request.urlopen 打开网页,使用BeautifulSoup解析打开的网页;2. 使用BeautifulSoup.find功能找到网页中的链接,然后将链接存入List中;3.转到步骤1,继续打开网页,重复depth次。
    • 程序要点:1. (非常重要)打开网页要设置时间间隔,不能打开一个后马上下一个,否则一方面可能会被网站拉入黑名单,从而拒绝你的网页请求,另一方面会造成网站服务器的压力,造成不必要的麻烦;2. 记录网页爬行的路径,避免重复爬行,这个可以通过字典、数据库等好多方式实现;3要分清爬行到的记录是否为网站内部网页,经常出现的一种情况是爬着爬着就不知道爬到哪里去了,大型网站平均每个网页都会有好几千个链接,如果不设定爬行边界,那爬行的网页数量将呈指数级增长,这是我们不希望看到的;4. 虽然有很多链接看起来不一样,但实际上二者是同一个网页,比如说网站的内容页:http://www.81.cn/jmywyl/2018-07/06/content_8081243.htmhttp://www.81.cn/jmywyl/2018-07/06/content_8081840.htmhttp://www.81.cn/jmywyl/2018-07/06/content_8081240.htm ,这些链接看起来是不同的,但实际上他们采用了同一个模板自动生成,如果想将他们记为一类,则需要下点功夫进行归类了。

    下面的程序只实现了程序要点中的1、2、3。实现方法都是最简单、基础的方法。至于如何实现4,还在进一步思考中,将在下一篇中更新。

    欢迎留言探讨更深一步的优化

    代码实现主要包括以下几个部分:

    • [x] 定义一个类,包装整个爬取的程序 UrlParser
    • [x] 定义一个根据当前页面搜索包含链接列表的方法 Parser
    • [x] 定义一个可以存储链接之间相互联系的字典,并设置添加节点的方法 addNode
    • [x] 定义一个可以判断链接是否为内部链接的方法 isInnerLink
    • [x] 定义一个存储爬取结果的方法 saveGraph

    代码如下:

    
    # -*- coding: utf-8 -*-
    """
    # -*- coding: utf-8 -*-
    """
    Spyder Editor
    
    This is a temporary script file.
    """
    from urllib.request import urlopen
    from bs4 import BeautifulSoup
    import pandas as pd
    import time
    import random
    import re
    import logging
    
    class UrlParser:
        def __init__(self,domain,depth,domainName):
            self.domain = domain
            print(self.domain)
            self.depth = depth
            self.domainName = domainName
            self.LinkGraph= {}
            self.LinkGraph[self.domain] = self.domain
            logging.basicConfig(filename='D://example.txt',level=logging.DEBUG)
            logging.info('=====================starting==========')
        #使用字典存储网页之间的连接关系  
        def addNode(self, parent,children):
            if(self.LinkGraph.get(children)!=None):
                return False
            else:
                self.LinkGraph[children] = parent
                return True
            
        #判断一个链接是否为网站内部的链接
        def isInnerLink(self,url):
            # url 以http开头 则判断是否在同一个domain下
            # url 不以http开头 则将url 补全
            if(url==None):
                return ''
            if(url.startswith('http')):
                if(re.match(r'^https*://\w*\.'+self.domainName+'\.',url)!=None):
                    return url
                else:
                    return ''
            else:
                if(url.startswith('//')):
                    url = url[2:]
                    if(re.match(r'\w*\.'+self.domainName+'\.',url)!=None):
                        return 'http://'+url
                    else:
                        return ''
                elif(url.startswith('/')):
                    return self.domain+url                
                else:
                    if(re.match(r'\w*\.'+self.domainName+'\.',url)!=None):
                        return 'http://'+url
                    else:
                        return ''    
        #依次访问LinkListpre中的链接指向的网页,并分析网页,得到网页中的链接
        def Parser(self,LinkListpre,LinkListnext):
            for url in LinkListpre:
                print(url)
                try:
                    html = urlopen(url)
                except BaseException as e:
                    logging.error('Parser::::warmning: url cannot open:::'+url)
                    continue;
                try:
                    bsObj = BeautifulSoup(html.read(),'lxml')
                    for link in bsObj.find_all('a'):
                        #print(link)
                        try:
                            link = link['href']
                        except KeyError as e:
                            continue
                        
                        #是内部链接
                        link = self.isInnerLink(link)
                        #长度超过2 是内部链接 且没有访问过 
                        if ((len(link.rstrip())>2)):
                            if(self.addNode(url,link)):
                                LinkListnext.append(link)
                except BaseException as e:
                    logging.error('Parser::::warmning: page cannot be parsed:::'+url)
                #模拟人类点击习惯,设置随机间隔
                time.sleep(1+random.random())
            return True
        def saveGraph(self):
            Gra = pd.DataFrame({'next':self.LinkGraph})
            Gra.to_csv('project1/test.csv')
        def Go(self):
            LinkListpre = [self.domain]
            LinkListnext = []
            
            for i in range(self.depth):
                print('====================')            
                self.Parser(LinkListpre,LinkListnext)
                print(len(LinkListnext))
                LinkListpre = LinkListnext
                LinkListnext = []
                if(len(LinkListpre)<1):
                    print('*********')
                    break
            self.saveGraph()
    
    MyParser = UrlParser('https://XXX.mycooper.com',2,'mycooper')   
    MyParser.Go()    
     
    

    相关文章

      网友评论

          本文标题:课程设计 Python 网络爬虫(广度优先方法)

          本文链接:https://www.haomeiwen.com/subject/lzlyuftx.html