Каждый должен был столкнуться с этой ситуацией при сканировании сети.
Когда я печатаю исходный код веб-страницы
Нашел все искаженное
Что нам делать тогда?
Как запросы определяют кодировку
Во-первых, содержимое, возвращаемое 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
Первоначально эта статья заканчивалась здесь. . . но. . .
Немного познаний в популярной науке
Есть несколько способов узнать кодировку веб-страницы?
- Говорили о выше response.headers с использованием content_type
- Предположено chardet.detect (упомянутый выше)
- Мета (и значение 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
Если есть еще способ угадать кодировку, пожалуйста, оставьте сообщение
над...