そこで、検索エンジン用のクローラーを作ろうとしています。コードはほとんど完成しています。仕組みは次のとおりです。
- 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,}| ', ' ', 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)
これから得た出力を添付しますが、サイトを始めたばかりで、2つ以上のリンクを含む質問を投稿できません:(これが長くて紛らわしく、単純に意味をなさない場合は申し訳ありません