Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用BeautifulSoup创建爬虫,URL索引问题_Python_Indexing_Beautifulsoup_Web Crawler - Fatal编程技术网

Python 使用BeautifulSoup创建爬虫,URL索引问题

Python 使用BeautifulSoup创建爬虫,URL索引问题,python,indexing,beautifulsoup,web-crawler,Python,Indexing,Beautifulsoup,Web Crawler,所以我试图为搜索引擎制作一个爬虫。我的代码基本上是完整的。它的工作方式是: 要使用BeautifulSoup打开页面 将url和docID保存到索引(在本例中仅为文本文件) 获取一些干净的文本并将其保存到文本文件中 获取页面上的所有URL,并将其添加到页面列表(如果该列表尚未在索引中) 我遇到的问题是,有时,它会多次索引URL 我做的一个例子是使用初始的pages=[”http://www.ece.udel.edu“]。在输出文件中,每行包含一个docID和一个url。其格式为docID u

所以我试图为搜索引擎制作一个爬虫。我的代码基本上是完整的。它的工作方式是:

  • 要使用BeautifulSoup打开页面
  • 将url和docID保存到索引(在本例中仅为文本文件)
  • 获取一些干净的文本并将其保存到文本文件中
  • 获取页面上的所有URL,并将其添加到页面列表(如果该列表尚未在索引中)
我遇到的问题是,有时,它会多次索引URL

我做的一个例子是使用初始的
pages=[”http://www.ece.udel.edu“]
。在输出文件中,每行包含一个docID和一个url。其格式为
docID url\n
。这将导致在对结果进行排名时出现问题,因为虽然它应该对这些结果进行相同的排名,但我将对同一页面的多个页面(每个页面具有不同的docID)进行排名

这是我到目前为止的代码。我试图对它进行彻底的评论,以便更容易理解

def cleanText(soup):
    #remove all unnecessary tags & punctuation leaving text of all lowercase letters & words
    texts = soup.findAll(text=True)
    visible_elements=[]
    for elem in texts:
        if elem.parent.name in ['style', 'script', '[document]', 'head', 'title']:
            visible_elements.append('')
        elem = elem.encode('utf-8','replace')
        result = re.sub('<!--.*-->|\r|\n', '', str(elem), flags=re.DOTALL)
        result = re.sub('\s{2,}|&nbsp;', ' ', result)
        visible_elements.append(result)
    visible_text = ' '.join(visible_elements)
    visible_text = re.sub('[^0-9a-zA-Z]+', ' ', visible_text)
    visible_text = visible_text.lower()
    return visible_text

def naming(pagename, pathToOutput):
    #used to create filename to save output text file
    cantBeInFilename = ("/", "\\",":","*","?","<",">","|")
    for k in range(len(cantBeInFilename)):
        pagename = pagename.replace(cantBeInFilename[k], "-")
    filename = "\\".join((pathToOutput, pagename))
    filename = ".".join((filename, "txt"))
    return filename

def crawl(pages, pathToOutput, pathToLinks):
    depth = len(pages)
    docID = 1
    for i in range(depth): #for each link on the page
        newpages=set() #create an empty set for gathered pages
        for page in pages: #each page in pages, initially atleast 1
            linksText = open(pathToLinks, 'a') #open a file
            linksText.write(str(docID) + " "); #write a docID to identify page
            docID = docID + 1 #increment docID
            linksText.write(str(page) + '\n') #append link into end of file
            linksText.close() #close file to update
            try:
                c = urllib2.urlopen(page) #open the page
                print ("Opening " + page)
            except:
                print ("Could not open " + page)
                continue
            soup = BeautifulSoup(c.read())
            clean_text = cleanText(soup)
            #get all links off page
            links = soup.findAll('a')
            #write web page to text file in pathToOutput directory
            filename = naming(page, pathToOutput)
            f = open(filename, 'w')
            f.write(clean_text)
            f.close()
            depth = 0
            for link in links:
                if('href' in dict(link.attrs)):
                    #set depth equal to the # of links in the pages
                    depth = depth+1
                    url = urljoin(page, link['href'])
                    #remove unnecessary portions of url
                    if url.find("'") != -1:
                        continue
                    url = url.split('#')[0]
                    #get each line (each link) from linksText
                    linksText = open(pathToLinks, 'r')
                    lines = linksText.readlines()
                    linksText.close()
                    #remove docIDs just to have 
                    for j in range(len(lines)):
                        lines[j-1] = lines[j-1].split()[1]
                    #FOR ALL LINKS
                    if url[0:4] == "http":
                        #check to see if the url ends with a /, if so remove it
                        if url[len(url)-1]=="/":
                            url = url[0:len(url)-1]
                        #check to see if the url is already in links
                        present = 0
                        for line in lines:
                            if (url == line):
                                present = 1
                            else:
                                present = 0
                        #if the url isn't present, add to pages to be cycled through
                        if (present == 0):
                            print ("Indexing " + url)
                            newpages.add(url)
                #add newpages to pages
                for newpage in newpages:
                    pages.append(newpage)
                newpages = set()
            #remove already read page from pages
            pages.remove(page)
def cleanText(汤):
#删除所有不必要的标记和标点符号,留下所有小写字母和单词的文本
text=soup.findAll(text=True)
可见元素=[]
对于文本中的元素:
如果elem.parent.name在['style','script','document','head','title']中:
可见元素。附加(“”)
元素=元素编码('utf-8','replace')
结果=re.sub('|\r |\n','',str(elem),flags=re.DOTALL)
result=re.sub('\s{2,}|','',result)
可见元素。追加(结果)
可见的\u文本=“”.join(可见的\u元素)
可见文本=re.sub(“[^0-9a-zA-Z]+”,“,可见文本)
可见文本=可见文本。下()
返回可见的文本
def命名(页面名、路径输出):
#用于创建文件名以保存输出文本文件
cantBeInFilename=(“/”、“\\”、“:”、“*”、“?”、“,”、“|”)等)
对于范围内的k(len(cantBeInFilename)):
pagename=pagename.replace(cantBeInFilename[k],“-”)
filename=“\\”.join((路径输出,页面名称))
filename=“.”.join((filename,“txt”))
返回文件名
def爬网(页面、路径输出、路径链接):
深度=长度(页数)
docID=1
对于范围内的i(深度):#对于页面上的每个链接
newpages=set()#为收集的页面创建一个空集
对于页面中的页面:#页面中的每个页面,最初至少1页
linksText=open(路径链接,'a')#打开一个文件
linksText.write(str(docID)+“”#编写文档ID以标识页面
docID=docID+1#增量docID
write(str(page)+'\n')#将链接追加到文件末尾
linksText.close()#关闭要更新的文件
尝试:
c=urllib2.urlopen(第页)#打开页面
打印(“打开”+页)
除:
打印(“无法打开”+页)
持续
soup=BeautifulSoup(c.read())
clean_text=cleanText(汤)
#获取页面上的所有链接
links=soup.findAll('a')
#将网页写入pathToOutput目录中的文本文件
filename=命名(第页,路径输出)
f=打开(文件名为“w”)
f、 写入(干净的文本)
f、 关闭()
深度=0
对于链接中的链接:
如果dict(link.attrs)中的('href'):
#将深度设置为页面中链接的#
深度=深度+1
url=urljoin(页面,链接['href'])
#删除url中不必要的部分
如果url.find(“”)=-1:
持续
url=url.split(“#”)[0]
#从linksText获取每行(每个链接)
linksText=open(路径链接'r')
lines=linksText.readlines()
linksText.close()
#删除docid只是为了
对于范围内的j(长度(线)):
行[j-1]=行[j-1]。拆分()[1]
#适用于所有链接
如果url[0:4]=“http”:
#检查url是否以/结尾,如果是,请将其删除
如果url[len(url)-1]==“/”:
url=url[0:len(url)-1]
#检查url是否已在链接中
当前=0
对于行中的行:
如果(url==行):
当前=1
其他:
当前=0
#如果url不存在,请添加到要循环浏览的页面
如果(当前==0):
打印(“索引”+url)
newpages.add(url)
#向页面添加新页面
对于newpage中的newpage:
pages.append(newpage)
newpages=set()
#从页面中删除已读页面
页面。删除(第页)

我想附上我已经从中获得的输出,但我刚刚开始在网站上发布一个带有两个以上链接的问题:(抱歉,如果这个链接太长,太混乱,太简单了,没有任何意义

这个代码片段没有做你认为的事情

present = 0
for line in lines:
    if (url == line):
        present = 1
    else:
        present = 0
#if the url isn't present, add to pages to be cycled through
if (present == 0):
    print ("Indexing " + url)
    newpages.add(url)
如果匹配在字符串的最后一项上,则只会保留
present=1
。测试它的更简单方法是:

#if the url isn't present, add to pages to be cycled through
if url not in lines:
    print ("Indexing " + url)
    newpages.add(url)
你也可能需要改变

#get each line (each link) from linksText
linksText = open(pathToLinks, 'r')
lines = linksText.readlines()
linksText.close()
进入


因此,
中的每一行都不会以
\n

结尾。我更改了您建议的两件事。对于第一件事,它似乎没有解决问题。我在更改了几行之后重新运行,仍然收到了具有不同docid的重复链接。至于第二件建议,我认为没有必要使用下一行表示范围内的j(len(line)):line[j]=l
#get each line (each link) from linksText
linksText = open(pathToLinks, 'r')
lines = linksText.read().split('\n')
linksText.close()