@kablihin

Почему crawler, работает 7 часов? Не зациклен ли код?

Начал изучение python. Написал паука, который обходит страницы и записывает их в бд с глубиной 3. Я, конечно, понимаю, что он не распараллелен, и это долгий процесс + я несовсем верно сделал комиты в бд. Но он работает уже 7 часов, и прошел даже не половину страниц. Я думаю, что я где-то зациклил код.

crawler
import re
import bs4
import requests
from db import Db
from bs4 import BeautifulSoup
from urllib.parse import urlparse, urljoin

class Crawler:
    def __init__(self, ignoreWords):
        self.ignoreWords = ignoreWords
        '''/*self.listSites = listSites
        self.depth = depth
        '''
        self.Db = Db('myDB.db')

    def crawl(self,sitesList,depth, morph):
        tmpSitesList = []
        counter = 0
        file = open('word.txt', 'w')
        file2 = open('link.txt', 'w')
        file3 = open("urls.txt",'w')
        i=0
        while i != depth:
            for site in sitesList:

                counter += 1
                sitesList.pop(0)
                '''if i==0:
                    self.Db.addLink(site)'''
                try:
                    #print("{}/{} {} Попытка открыть {} ...".format(counter, len(sitesList), site))
                    html_doc = requests.get(site).text  # получить HTML код страницы
                except Exception as e:
                    # обработка исключений при ошибке запроса содержимого страницы
                    print(e)
                    continue  # перейти к следующему url
                soup = bs4.BeautifulSoup(html_doc, "html.parser")
                # шаг-4. Найти на странице блоки со скриптами и стилями оформления ('script', 'style')
                listUnwantedItems = ['script', 'style']
                for script in soup.find_all(listUnwantedItems):
                    script.decompose()  # очистить содержимое элемента и удалить его из дерева
                if (self.isIndexed(site) == True):
                    continue
                self.addIndex(site,soup,morph)
                print("Я обрабатал ссылку ")
                aaaa = self.Db.returnIdUrl(site)
                file3.write(str(aaaa[0]) + ' '+ str(aaaa[1]) + ' depth ' + str(depth) + '\n')
                count = self.Db.countWord()

                file.write(str(count[0]) + ' ' + str(counter) + '\n')




                foundLinks = soup.find_all('a')
                for link in foundLinks:
                    if 'href' in link.attrs:
                        linkUrl = link.attrs['href']
                        if linkUrl.startswith("http") and link != site:
                            if linkUrl != site and linkUrl !='/':
                                self.addLinkRef(site, linkUrl)
                                if linkUrl not in tmpSitesList and self.isIndexed(linkUrl) == False:
                                    tmpSitesList.append(linkUrl)
                        else:
                            if linkUrl !='/':
                                linkUrl = link.attrs['href']
                                url = urljoin(site, linkUrl)
                                if url != site:
                                    self.addLinkRef(site, url)
                                    if linkUrl not in tmpSitesList and self.isIndexed(linkUrl) == False:
                                        tmpSitesList.append(url)
                countLink = self.Db.countLinkBetween()
                file2.write(str(countLink[0]) + " " + str(counter)+ "\n")

            if len(sitesList) == 0 :
                sitesList = tmpSitesList.copy()
                tmpSitesList.clear()
                i=i+1
        file.close()
        file2.close()
        file3.close()



    def addIndex(self, url, soup,morph,ignoreWords = []):
        if(self.isIndexed(url)):
            return
        #print(soup)
        self.Db.addLink(url)
        text = self.getTextOnly(soup)
        words = self.separateWords(text)
        print(words)
        for id,word in enumerate(words):
            p = morph.parse(word)[0]
            if p.tag.POS != 'INTJ':
                worded = self.getEntryId('worldList', 'word',word, True)
                wordedLocation = self.Db.createIndexLocation(url,worded[0],id)



    def getTextOnly(self, soup):
        result = ''
        #Получить все div
        allDivs = soup.find_all('div')

        #Получить весь текст из div
        for div in allDivs:
            result +=div.get_text()
        return result.strip()


    def separateWords(self, text):
        wordsList = []
        tmp = ''
        text = re.sub("\xa0", " ", text)

        for i in range(0,len(text)):
            if text[i] != " " and text[i] !="\n" and text[i]!='':
                tmp += text[i]
            if text[i] == "\n" and text[i+1]!="\n" or text[i] == " ":
                if text[i] != '' and tmp!='':
                    wordsList.append(tmp)
                    tmp = ''

        return wordsList

    def isIndexed(self,url):
        return self.Db.isIndexed(url)


    def addLinkRef(self,urlForm,urlTo):
        self.Db.addLink(urlTo)
        self.Db.addLinkBetween(urlForm,urlTo)
        pass


    def createIndexTables(self):
        pass

    def getEntryId(self, table,field,value,createNew):
        return self.Db.getIndex(table, field, value, createNew)
  • Вопрос задан
  • 49 просмотров
Пригласить эксперта
Ответы на вопрос 2
@loharik229
Возможно, ошибкой является while i != depth:. Некоторые сайты могут не соответствовать такой глубине и будут бесконечно искаться.
Ответ написан
Комментировать
mayton2019
@mayton2019
Bigdata Engineer
Некоторые сайты могут сдетектировать бота и подкинуть свинью. Например - отдавать бесконечный поток шумящего html-кода который просто нагружает работой BeautifulSoup. Но чтобы говорить о зависании - надо сначала придумать формальный критерий. Например - парсинг одного url запускается в отдельном потоке и lifetime потока не должен превышать к примеру 30 секунд. Если превышает - мы считаем что он глотает шум или не получает контента. И прибиваем поток. ЛОггируем событие и идем дальше по ссылкам.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы