Как исправить ошибку кодирования, когда Python пишет в HTML - PullRequest
0 голосов
/ 27 июня 2019

Я создал веб-парсер с использованием Python 3.7 и Beautifulsoup. Затем я использовал "find_all", чтобы найти все теги с определенным классом. Что-то важное в том, что на сайте, на котором я работаю, есть китайские иероглифы. Вот мой код:

import requests
from bs4 import BeautifulSoup

response = requests.get('URL_GOES_HERE')
soup = BeautifulSoup(response.content, 'html.parser')
posts = soup.find_all(class_='CLASS_GOES_HERE')

print(posts)

saveFile = open('index.html','w+')
saveFile.write(str(posts))
saveFile.close()

Я попытался вывести данные двумя разными способами: распечатав данные на консоль и записав их в HTML-документ. Я делал каждый по отдельности, «комментируя» функцию печати при записи в HTML, и наоборот.

Когда я запускаю только функцию печати, данные выводятся на консоль без ошибок. Однако, когда я запускаю функцию записи в HTML, я получаю следующую ошибку кодирования:

Traceback (most recent call last):
  File "postthis.py", line 11, in <module>
    saveFile.write(str(posts))
  File "C:\Users\atit1\AppData\Local\Programs\Python\Python37\lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 4308-4324: character maps to <undefined>"

Последние два дня я пытался это исправить, руководствуясь многими похожими вопросами по Stackoverflow. Многие ответы предлагали добавить ".encode (" utf-8 ")", поэтому я попробовал это. Например, когда я пытаюсь написать .write (str (soup)), я получаю ошибку кодирования. Но когда я пишу это, он отлично работает:

saveFile.write(str(soup.encode("utf-8")))

Однако проблема в том, что это напечатает весь HTML-документ веб-сайта в мой HTML-документ, а я хочу, чтобы он написал только некоторые классы. Логически (э-э, может быть, нет?) Я попытался добавить .encode к моей переменной posts следующим образом:

saveFile.write(str(posts.encode("utf-8")))

Но я продолжаю сталкиваться с этой ошибкой и не могу понять, почему:

Traceback (most recent call last):
  File "webscraper.py", line 21, in <module>
    saveFile.write(str(posts.encode("utf-8")))
  File "C:\Users\atit1\AppData\Local\Programs\Python\Python37\lib\site-packages\bs4\element.py", line 1620, in __getattr__
    "ResultSet object has no attribute '%s'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?" % key
AttributeError: ResultSet object has no attribute 'encode'. You're probably treating a list of items like a single item. Did you
call find_all() when you meant to call find()?

У кого-нибудь есть предложения по исправлению этой ошибки? Кстати, все, что мне нужно, это текст на английском языке с веб-сайта, так что, если ваше решение пропустит / повредит специальные китайские символы, это нормально.

EDIT 1 Вот часть исходного кода HTML, которую я пытаюсь проанализировать. Существует около 50 таких списков, и некоторые из них содержат иностранные имена, поэтому я получаю эту ошибку кодирования, когда пытаюсь разобрать это.

<li>
    <div itemscope="SOME_WORDS" itemid="SOME_URL" itemtype="SOME_URL">\

        <meta itemprop="url" content="SOME_URL"/>
        <a class="THE_CLASS_I_WANT"  href="THE_URL_I_WANT">

            <span itemprop="SOME_WORDS">
                THE TEXT I WANT 
            </span>
        </a> 

    </div>      
</li>   

1 Ответ

2 голосов
/ 27 июня 2019

Вы пытаетесь вызвать метод .encode() для posts, у которого его нет.posts было возвращено find_all() - при условии, что вы действительно хотите найти все из них, вам придется кодировать все найденные элементы отдельно.

Кроме того, вместо записи всего списка сообщений в файлв виде списка, вы, вероятно, захотите создать действительный HTML-документ, что является еще одной проблемой в целом.

Чтобы делать то, что вы делаете (даже если я думаю, что это не то, что вы в конечном итоге хотите):

saveFile = open('index.html','w+')
saveFile.write(str([post.encode('utf-8') for post in posts]))
saveFile.close()

Или, возможно, немного лучше, но, возможно, все еще не совсем тот результат, который вам может понадобиться:

saveFile = open('index.html','wb+')
for post in posts:
    saveFile.write(post.encode('utf-8'))
saveFile.close()

Обратите внимание на важные различия: вместо простого написания преобразования строкииз всего списка каждый элемент кодируется отдельно, и результирующие bytes записываются в файл, который был открыт в двоичном (не текстовом) режиме с помощью wb.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...