Вопрос

Я перепроверил свой код и рассмотрел сопоставимые операции по открытию URL-адреса для передачи веб-данных в Beautiful Soup, но по какой-то причине мой код просто ничего не возвращает, хотя он находится в правильной форме:

>>> from bs4 import BeautifulSoup

>>> from urllib3 import poolmanager

>>> connectBuilder = poolmanager.PoolManager()

>>> content = connectBuilder.urlopen('GET', 'http://www.crummy.com/software/BeautifulSoup/')

>>> content
<urllib3.response.HTTPResponse object at 0x00000000032EC390>

>>> soup = BeautifulSoup(content)

>>> soup.title
>>> soup.title.name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'name'
>>> soup.p
>>> soup.get_text()
''

>>> content.data
a stream of data follows...

Как показано, ясно, что urlopen() возвращает HTTP-ответ, который фиксируется содержимым переменной. Имеет смысл, что он может читать статус ответа, но после того, как он передан в Beautiful Soup, веб-данные не преобразуются. в объект Beautiful Soup (переменный суп).Вы можете видеть, что я попытался прочитать несколько тегов и текста, get_text() возвращает пустой список, это странно.

Как ни странно, когда я получаю доступ к веб-данным через content.data, данные появляются, но бесполезны, поскольку я не могу использовать Beautiful Soup для их анализа.В чем моя проблема?Спасибо.

Это было полезно?

Решение

Если вы просто хотите прославить страницу, requests получит необходимое контент:

from bs4 import BeautifulSoup

import requests
r = requests.get('http://www.crummy.com/software/BeautifulSoup/')
soup = BeautifulSoup(r.content)

In [59]: soup.title
Out[59]: <title>Beautiful Soup: We called him Tortoise because he taught us.</title>

In [60]: soup.title.name
Out[60]: 'title'
.

Другие советы

urllib3 возвращает объект Response, который содержит .data который имеет предварительно загруженную полезную нагрузку тела.

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

import urllib3
http = urllib3.PoolManager()
response = http.request('GET', 'http://www.crummy.com/software/BeautifulSoup/')

from bs4 import BeautifulSoup
soup = BeautifulSoup(response.data)  # Note the use of the .data property
...

Остальное должно работать как задумано.

--

Немного о том, что пошло не так в исходном коде:

Ты прошел весь response объект, а не полезная нагрузка тела.Обычно это нормально, потому что response объект представляет собой файлоподобный объект, кроме в этом случае urllib3 уже поглощает весь ответ и анализирует его за вас, так что больше нечего делать. .read().Это похоже на передачу указателя файла, который уже был прочитан. .data с другой стороны, получит доступ к уже прочитанным данным.

Если вы хотите использовать объекты ответа urllib3 как файловые объекты, вам необходимо отключить предварительную загрузку контента, например:

response = http.request('GET', 'http://www.crummy.com/software/BeautifulSoup/', preload_content=False)
soup = BeautifulSoup(response)  # We can pass the original `response` object now.

Теперь все должно работать так, как вы ожидали.

Я понимаю, что это не очень очевидное поведение, и как автор urllib3 прошу прощения.:) Планируем сделать preload_content=False по умолчанию когда-нибудь.Возможно, когда-нибудь скоро (Я открыл здесь проблему).

--

Небольшая заметка о .urlopen против .request:

.urlopen предполагает, что вы позаботитесь о кодировании любых параметров, передаваемых в запрос.В этом случае можно использовать .urlopen потому что вы не передаете в запрос никаких параметров, но в целом .request сделает всю дополнительную работу за вас, так что это будет удобнее.

Если кто-то захочет улучшить нашу документацию в этом отношении, мы будем очень признательны.:) Пожалуйста, отправьте PR на https://github.com/shazow/urllib3 и добавьте себя в качестве участника!

Как показано, ясно, что urlopen() возвращает HTTP-ответ, который фиксируется содержимым переменной…

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

>>> response = connectBuilder.urlopen('GET', 'http://www.crummy.com/software/BeautifulSoup/')
>>> response
<urllib3.response.HTTPResponse object at 0x00000000032EC390>
>>> content = response.read()
>>> content
b''

Это должно прояснить, что BeautifulSoup проблема здесь не в этом.Но продолжаем:

… но после того, как они переданы в Beautiful Soup, веб-данные не преобразуются в объект Beautiful Soup (переменный суп).

Да, это так.Дело в том, что soup.title дал вам None вместо того, чтобы поднять AttributeError это довольно хорошее доказательство, но вы можете проверить его напрямую:

>>> type(soup)
bs4.BeautifulSoup

Это определенно BeautifulSoup объект.

Когда ты проходишь BeautifulSoup пустая строка, то, что вы получите обратно, будет зависеть от того, какой синтаксический анализатор используется под обложкой;если он опирается на стандартную библиотеку Python 3.x, вы получите html узел с пустым head, и пустой body, и ничего больше.Итак, когда вы ищете title узел, его нет, и вы получаете None.


Итак, как это исправить?

Как документация говорит, что вы используете «самый низкий уровень вызова для выполнения запроса, поэтому вам нужно указать все необработанные детали». Что это за сырые детали?Честно говоря, если вы еще не знаете, вам не следует использовать этот метод. urllib3 прежде чем вы даже узнаете основы, это не окажет вам услуги.

На самом деле, вам действительно не нужно urllib3 здесь вообще.Просто используйте модули, поставляемые с Python:

>>> # on Python 2.x, instead do: from urllib2 import urlopen 
>>> from urllib.request import urlopen
>>> r = urlopen('http://www.crummy.com/software/BeautifulSoup/')
>>> soup = BeautifulSoup(r)
>>> soup.title.text
'Beautiful Soup: We called him Tortoise because he taught us.'

Мой прекрасный код супа работал в одной среде (мою локальную машину) и возвращая пустой список в другом (сервер Ubuntu 14).

Я решил мою проблему, изменяя установку. Детали в другом потоке:

HTML Parsing с красивым супом Возвращает пустой список .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top