Очистите и проанализируйте сайт словаря и узнайте значение каждого слова в текстовом файле

В этой программе я произвел автоматизацию с помощью Selenium, чтобы найти английское значение каждого санскритского слова на сайте словаря.

Функция eng_meaning принимает слово и, используя селен, и BeautifulSoup перебирает веб-сайт и находит английское значение.

def eng_meaning(word):
    """
    returns english meaning of the sanskrit word passed
    """
    url="https://www.learnsanskrit.cc/index.php?mode=3&direct=au&script=hk&tran_input="
    driver = webdriver.Chrome("/usr/bin/chromedriver")
    driver.get(url)
    meanings = []

    try:
        #find text box where we enter the word
        text_box = driver.find_element_by_id("tran_input")

        #enter word in the text box
        text_box.send_keys(word)

        #clicking translate button
        buttons = driver.find_elements_by_tag_name("button")
        buttons[-1].click()

        html_page = driver.page_source
        #parse html page
        soup = BeautifulSoup(html_page, 'html.parser')
        #find table which holds meaning
        table = soup.body.find('table', attrs={'class':'table0 bgcolor0'})
        table_body = table.find('tbody')

        #find rows of table which holds meaning
        rows = table_body.find_all('tr')
        process = True #will become false if word/sentence other then passed word is on table
        row_itr = 0

        for row in rows:
            #find coulmns in the current row
            columns = row.find_all('td')
            i = 0

            for col in columns:

                #split, join and strip the current snaskrit or english word and store in meaning
                meaning =  " ".join(col.get_text().split())
                meaning = meaning.strip()

                if (i == 0):
                    tmp = meaning
                    if (row_itr == 0):
                        #add sanskrit word in the list. Only done once
                        sanskrit_word = meaning
                elif (i == 2):
                    if (row_itr == 0):
                        #add english transliteration in list. Only done once
                        english_transliteration = meaning

                    if (word != meaning and word != tmp):
                        #current word is process doesn't match with passed word. So stop processing
                        process = False
                        break
                elif (i == 3):
                    #append sanskrit word and english transliteration in list. Done only once
                    if (row_itr == 0):
                        meanings.append(sanskrit_word)
                        meanings.append(english_transliteration)
                    #append the english meaning to list
                    meanings.append(meaning)
                i+=1
            if (process is False):
                #stop processing
                break
            row_itr += 1
        return meanings
    except(Exception, AttributeError) as e:
        print("No meaning found for", word)

    finally:
        if len(meanings) != 0:
            print("meanings found")
        driver.quit()

Программа reading_writing_to_file.py читает текстовый файл на санскрите, удаляет повторяющиеся слова и сохраняет значение каждого слова в другом текстовом файле.

import sanskrit_to_english as se

def remove_duplicates(file_name):
    """
    Remove duplicate word from the file
    """
    unique_words = set()
    with open(file_name, 'r') as file:
        for line in file:
            for word in line.split():
                unique_words.add(word)
        file.close()
    return unique_words


def eng_translation(file_name_r, file_name_w):
    """
    Read sanskrit text file  and find english meaning of each word
    """
    words = list(remove_duplicates(file_name_r))

    with open(file_name_w, 'w') as file:
        for word in words:
            meanings = se.eng_meaning(word)
            if (meanings):
                file.write(meanings[0])
                file.write(" - ")
                file.write(meanings[1])
                file.write(" - ")
                meanings_str=" \".join([meanings[i] for i in range(2, len(meanings))])
                file.write(meanings_str)
                file.write("n")
    file.close()
    

file_name_r = "data.txt"
file_name_w = "Sanskrit_english.txt"
eng_translation(file_name_r, file_name_w)

Я новичок в селене. Как я могу улучшить производительность этого кода во время выполнения. Это занимает ок. 5 минут на поиск значения слова.

Сайт санскритского словаря — Learnsanskrit.cc

1 ответ
1

Самым очевидным узким местом в вашем коде является то, что вы вызываете функцию eng_meaning в цикле, но эта функция каждый раз создает новый экземпляр Selenium, что является дорогостоящей операцией. Представьте, что вы выполняете поиск в Google, а затем систематически закрываете и снова открываете браузер после каждого поиска. Пустая трата времени, не правда ли?

Что вам нужно сделать, так это реструктурировать свой код, чтобы запустить Selenium один раз при запуске вашей программы. Затем все, что вам нужно сделать, это изменить URL-адрес, отправить новые параметры и т. Д., Сохранив существующий экземпляр.

Это должно заметно ускорить процесс. Я не запускал вашу программу и не тестировал ее. Я рекомендую вам использовать модуль timeit или аналогичный для определения времени производительности вашего кода и выяснить разделы, в которых есть задержки. Или, по крайней мере, добавьте несколько отпечатков здесь и там в код, показывая текущий шаг выполнения и временную метку.

5 минут на слово — это действительно много, но также возможно, что веб-сайт применяет какую-либо форму ограничение скорости против активных пользователей или скребков (то есть вас).

Разные примечания

Предупреждение: у вас есть опечатки (орфографические ошибки).

Соглашения об именах для функций или переменных оставляем желать лучшего.

except(Exception, AttributeError) as e:

лишнее: Exception перехватит все, но вы можете просто перехватить AttributeError в этом контексте.

file.close() не требуется, когда вы используете диспетчер контекста (with)

В eng_meaning у вас есть цикл по строкам таблицы, который несколько запутан. Имена переменных, такие как tmp, не очень интуитивно понятны. Несмотря на комментарии, не сразу понятно, почему переменная process существует и то, что вы действительно пытаетесь сделать.

Способ увеличения переменных (счетчики строк / столбцов) подвержен ошибкам, особенно с двумя вложенными циклами с блоками условий. Вместо:

for row in rows:

у вас могло быть:

for row_counter, row in enumerate(rows, start=1):

тогда пусть Python позаботится об инкременте за вас. Возможно, в BS уже есть встроенные методы для получения индекса строки / столбца, я не уверен. Но это не то, что вам следует обрабатывать вручную.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *