Больше не нужно беспокоиться о ямах кодирования веб-страниц!

задняя часть внешний интерфейс GitHub

Каждый должен был столкнуться с этой ситуацией при сканировании сети.

Когда я печатаю исходный код веб-страницы

Нашел все искаженное

Что нам делать тогда?

Как запросы определяют кодировку

Во-первых, содержимое, возвращаемое response.content, является двоичным содержимым.

Response.text декодируется на основе набора кодировок

# Try charset from content-type  
content = None  
encoding = self.encoding  
  
if not self.content:  
  return str('')  
  
# Fallback to auto-detected encoding.  
if self.encoding is None:  
    encoding = self.apparent_encoding  
  
# Decode unicode from given encoding.  
try:  
    content = str(self.content, encoding, errors='replace')  
except (LookupError, TypeError):

Мы видим, что при кодировании None,

Кодировку получает chardet.detect,

def apparent_encoding(self):  
"""The apparent encoding, provided by the chardet library."""  
    return chardet.detect(self.content)['encoding']

Так что же делает chardet.detect?

Проще говоря, это вернуть его кодировку на основе заданного байта.

Что касается того, как он это реализует, добро пожаловать в исходный код. . .

Упоминается выше, при кодировании на время, ни один из запросов - это то, как установить кодировку

Итак, какова кодировка по умолчанию для кодирования? Продолжить просмотр исходного кода

Мы нашли его в adapters.py~

response.encoding = get_encoding_from_headers(response.headers)

def get_encoding_from_headers(headers):  
"""Returns encodings from given HTTP Header Dict.  
    :param headers: dictionary to extract encoding from.  
    :rtype: str  
    """  
    content_type = headers.get('content-type')  
  
if not content_type:  
  return None  
content_type, params = cgi.parse_header(content_type)  

if 'charset' in params:  
  return params['charset'].strip("'\"")  
  
if 'text' in content_type:  
  return 'ISO-8859-1'

Проще говоря, как вернуть заголовок без content_type, тогда кодировка None

Если charset находится в параметре, используйте значение, установленное charset (см. рисунок ниже, возвращенный github)

Если текст находится в параметре, используйтеISO-8859-1

Затем вы печатаете кодировку своей искаженной веб-страницы и обнаруживаете, что она действительноISO-8859-1

Вам будет интересно, почему, когда тип контента — text/html, используется кодировка iso-8859-1?

Разве сейчас не распространена кодировка utf8, почему запросы такие глупые...

Потом я узнал, что это регламент rfc2016. . .

Ссылка на rfc2016 находится по адресу https://www.ietf.org/rfc/rfc2616.txt.

Заинтересованные студенты могут проверить...

окончательное резюме

Когда возвращаемый заголовок не имеет content_type, кодирование использует кодировку, угаданную chardet.detect (обычно очень точную).

Когда в заголовке возврата содержится CONTENT_TYPE, если есть Charset = xxx, кодировка кодировки - это значение Chatset. Если это просто текст / HTML, кодировка ISO-8859-1

Так что же делать, если вы обнаружите, что response.text возвращает искаженные символы. . .

Просто сначала установите кодировку None...

Просто напечатайте .text еще раз..

response.encoding = None  
response.text

Первоначально эта статья заканчивалась здесь. . . но. . .

Немного познаний в популярной науке

Есть несколько способов узнать кодировку веб-страницы?

  1. Говорили о выше response.headers с использованием content_type
  2. Предположено chardet.detect (упомянутый выше)
  3. Мета (и значение charset) в исходном коде веб-страницы выглядит следующим образом, это означает, что код веб-страницы gb2312 (правда, иногда это не очень точно, это пишет фронтенд шторка хх, тогда вы можете используйте chardet.detect Просто догадываюсь...)

Как написать код метода 3 (ниже)

def get_encodings_from_content(content):  
"""Returns encodings from given content string.  
    :param content: bytestring to extract encodings from.  
    """  
    warnings.warn((  
'In requests 3.0, get_encodings_from_content will be removed. For '  
        'more information, please see the discussion on issue #2266. (This'  
        ' warning should only appear once.)'),  
        DeprecationWarning)  
  
    charset_re = re.compile(r'<meta.*?charset=["\']*(.+?)["\'>]', flags=re.I)  
    pragma_re = re.compile(r'<meta.*?content=["\']*;?charset=(.+?)["\'>]', flags=re.I)  
    xml_re = re.compile(r'^<\?xml.*?encoding=["\']*(.+?)["\'>]')  
  
    return (charset_re.findall(content) +  
            pragma_re.findall(content) +  
            xml_re.findall(content))

Когда вы увидите версию request3.0, этот метод будет удален, вот почему. . .

Сделайте скриншот и убедитесь сами, адрес https://github.com/requests/requests/issues/2266

Если есть еще способ угадать кодировку, пожалуйста, оставьте сообщение

над...