将Web数据传递到Beautiful Soup - 空列表

use*_*774 6 python beautifulsoup web-content web-scraping urllib3

我已经重新检查了我的代码并查看了打开URL以将Web数据传递到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...
Run Code Online (Sandbox Code Playgroud)

如图所示,很明显urlopen()返回一个由变量内容捕获的HTTP响应,它可以读取响应的状态,但是在它被传递到Beautiful Soup后,Web数据不会被转换成为一个美丽的汤对象(可变汤).你可以看到我试图读取一些标签和文本,get_text()返回一个空列表,这很奇怪.

奇怪的是,当我通过content.data访问网络数据时,数据显示但由于我不能使用Beautiful Soup来解析它,所以它没有用.我的问题是什么?谢谢.

Pad*_*ham 13

如果您只想抓取页面,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'
Run Code Online (Sandbox Code Playgroud)


sha*_*zow 12

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
...
Run Code Online (Sandbox Code Playgroud)

其余的应该按预期工作.

-

关于原始代码出了什么问题:

您传递了整个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.
Run Code Online (Sandbox Code Playgroud)

现在它应该按预期工作.

我明白这不是很明显的行为,而且作为urllib3的作者我道歉.:)我们计划preload_content=False有一天制作默认值.也许有一天很快(我在这里开了一个问题).

-

关于.urlopenvs 的快速说明.request:

.urlopen假设您将负责编码传递给请求的任何参数.在这种情况下,它可以使用,.urlopen因为你没有将任何参数传递给请求,但通常.request会为你做所有额外的工作,所以它更方便.

如果有人愿意为此改进我们的文档,那将非常感激.:)请发送PR到https://github.com/shazow/urllib3并添加自己作为贡献者!