Как я могу заменить коды символов HTML фактическими символами в тексте, полученными при очистке селена перед вставкой данных в sqlite db? - PullRequest
0 голосов
/ 16 января 2019

Я использую Selenium (Chromedriver) с Python 2.7, чтобы очистить сайт от динамического текста, который отображается в тегах. Внутри находится HTML-код, вложенный в объект JSON, который используется для создания списка содержимого на странице, которую я просматриваю, но меня интересует только получение текстового содержимого. Мне удалось выяснить, как очистить теги HTML, используя re, но текст по-прежнему содержит коды символов HTML для специальных символов, которые я хочу заменить символом, которому они соответствуют.

Так, например, скажем, мой json (после очистки HTML-тегов) выглядит следующим образом:

[
    {
        "data": {
            "published_on": "2019-01-15T08:46:00+00:00", 
            "id": "somealphanumericid", 
            "short_description": "Albert Einstein’s Theory of Relativity: Should We Worry…?", 
            "series": "Science", 
            "long_description": "Albert Einstein does an interview with Mr. John Smith about the application of the theory of relativity, and what it could mean for the future of the pizza industry!", 
            "duration": "752000", 
            "type": "video", 
            "title": "Albert Einstein’s Theory of Relativity:"
        }, 
        "links": {
            "permalink": "https://www.stackoverflow.com"
        }, 
        "key": "somealphanumericid"
    },
    ...
]

Редактировать: Объект JSON на самом деле является массивом объектов JSON, следовательно, []. Сайт, который я копирую, разбит на страницы, поэтому я получаю JSON с каждой страницы и в конце просто объединяю их в один массив, чтобы с ним было легче работать.

Вы можете видеть, что такие символы, как точки, запятые, двоеточия и т. Д., Очищаются как соответствующие им коды символов HTML.

Теперь я перебираю JSON и помещаю все в базу данных sqlite, поэтому не имеет значения, заменяю ли я коды символов в самом JSON или выполняю замену прямо перед тем, как помещать данные в дб.

Первое, что я попытался сделать, это использовать вторичную функцию, которая взяла строку в качестве аргумента и вернула строку с замененными символами. Я в основном изменил решение, которое можно найти здесь . Итак, эта функция была:

from BeautifulSoup import BeautifulStoneSoup

def HTMLEntitiesToUnicode(text):
    text = unicode(BeautifulStoneSoup(text, convertEntities=BeautifulStoneSoup.ALL_ENTITIES))
    return text

Я использовал это в цикле, который создает набор данных для строки данных, которые должны быть переданы в sqlite следующим образом:

def json_to_rows(json_file):
    with open(json_file, 'r') as infile:
        data = json.load(infile)
        data_as_rows = []
        length = len(data)
        for i in range(0, length, 1):
            data_as_rows.append((
                data[i]['key'],
                data[i]['data']['id'],
                data[i]['links']['permalink'],
                HTMLEntitiesToUnicode(data[i]['data']['series']),
                HTMLEntitiesToUnicode(data[i]['data']['title']),
                data[i]['data']['published_on'],
                data[i]['data']['type'],
                data[i]['data']['duration'],
                HTMLEntitiesToUnicode(data[i]['data']['short_description']),
                HTMLEntitiesToUnicode(data[i]['data']['long_description']),
                ))

    return data_as_rows

Однако это привело к следующей ошибке при разборе HTMLEntitiesToUnicode(data[i]['data']['series']):

File "BeautifulSoup.py", line 1918, in _detectEncoding
    '^<\?.*encoding=[\'"](.*?)[\'"].*\?>').match(xml_data)
TypeError: expected string or buffer

Я не могу понять, почему BeautifulSoup не видит это как строку, но я попытался изменить ее на:

HTMLEntitiesToUnicode(str(data[i]['data']['series']))

Что тогда дало мне ошибку:

File "support.py", line 162, in json_to_rows
    HTMLEntitiesToUnicode(str(data[i]['data']['series'])),
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2019' in position 129: ordinal not in range(128)

Добавление .encode('utf-8') также не устраняет ошибку (это было рекомендовано для других сообщений с таким же сообщением об ошибке).

Моя конечная цель - просто собрать всю эту информацию в БД, чтобы она была отформатирована как обычный разборчивый текст (кроме длительности, которая в любом случае имеет тип INTEGER).

Я хотел бы сделать замену символов до / после подачи данных в БД, но также возможно, что я могу перебирать БД в отдельной функции и очищать ее, хотя это выглядит как гораздо менее эффективный способ сделать это.

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Оказывается, причина, по которой HTMLEntitiesToUnicode() не работал для меня, заключалась в том, что я читал данные из файла .json, в который были записаны данные, без указания того, что он должен быть сохранен в utf-8. Исправление и последующее использование HTMLEntititesToUnicode(), как описано выше, работало нормально.

0 голосов
/ 16 января 2019

Я думаю, что проблема, с которой вы столкнулись выше, заключается в том, что ваш текст уже в формате Unicode, и вы пытаетесь преобразовать его в Unicode во второй раз, что вызывает вашу ошибку.

Код ниже работал для меня и дал результаты, показанные ниже.

from bs4 import BeautifulSoup

text = "Albert Einstein&#8217;s Theory of Relativity&#58; Should We Worry&#8230;&#63;"
parsed_html = BeautifulSoup(text)

print 'Original Type: ' + type(text)
print 'Original Text: ' + text
print 'Parsed Type:   ' + type(parsed_html.text)
print 'Parsed Text:   ' + parsed_html.text

Выход:

Original Type: <type 'str'>
Original Text: Albert Einstein&#8217;s Theory of Relativity&#58; Should We Worry&#8230;&#63;
Parsed Type: <type 'unicode'>
Parsed Text: Albert Einstein’s Theory of Relativity: Should We Worry…?

Использование BeautifulSoup4 версии 4.7.1

pip install bs4

...