调用read()后bsObj1及未操作的bsObj3为空的原因与解决方法
问题:调用read()提取内容后,bsObj1和bsObj3文本为何变为空白?如何避免bsObj1被自动修改?
先看这段代码:
from urllib.request import urlopen from bs4 import BeautifulSoup def getLinks(pageUrl): html1 = urlopen(pageUrl) html2 = urlopen(pageUrl) html3 = html1 body1 = html1.read() bsObj1 = BeautifulSoup(html1, "html.parser") bsObj2 = BeautifulSoup(html2, "html.parser") bsObj3 = BeautifulSoup(html3, "html.parser") # 打印后会发现bsObj1、bsObj3内容为空,只有bsObj2正常
运行这段代码时会遇到一个奇怪的问题:调用read()提取html1的内容后,bsObj1的文本变成了空白;明明没碰过bsObj3,它的文本也跟着空了。这到底是咋回事?又该怎么解决呢?
为啥会出现这种情况?
我给你拆解两个核心原因:
- 类文件对象的指针特性:
urlopen()返回的是个类文件对象,这类对象有个“文件指针”的东西——你调用read()的时候,它会一次性把所有内容读完,同时把指针直接移到内容的最末尾。这时候你再把这个对象传给BeautifulSoup,它会从当前指针位置开始读内容,那可不就是啥都读不到嘛?这就是bsObj1变空白的直接原因。 - 对象引用不是复制:你写的
html3 = html1,可不是给html1复制了一个新对象哦,而是让html3和html1指向同一个内存里的对象。也就是说,它们俩其实是同一个东西的两个名字。所以当html1的指针被移到末尾后,html3的指针位置也跟着变了,传给BeautifulSoup自然也读不到内容。
怎么解决?
给你三个实用的办法,按需选就行:
- 办法一:读完后把指针移回去:在调用
read()之后,用seek(0)把指针拉回内容开头,这样BeautifulSoup就能重新读到完整内容了:body1 = html1.read() html1.seek(0) # 把指针移到文件开头 bsObj1 = BeautifulSoup(html1, "html.parser") - 办法二:直接传读取到的字符串:既然你已经用
read()拿到了字符串格式的body1,直接把这个字符串传给BeautifulSoup就好,不用再用原来的类文件对象:body1 = html1.read() bsObj1 = BeautifulSoup(body1, "html.parser") - 办法三:别共用同一个对象:如果需要多个独立的可读取对象,别直接赋值引用,像你对html2那样,重新调用
urlopen()创建新对象就行,这样每个对象的指针都是独立的,不会互相干扰。
内容的提问来源于stack exchange,提问作者H42
相关产品推荐
相关产品推荐

