相同的CSS,浏览器和bs4 .select()方法的结果不同

时间:2018-12-14 00:12:49

标签: python parsing beautifulsoup css-selectors

我正在尝试从以下网页中检索一些信息: https://web.archive.org/web/19990421025223/http://www.rbc.ru

我构造了一个选择器,该选择器在Chrome的“检查”模式下突出显示了所需的表格:

selector = 'body > table:nth-of-type(2) > tbody:nth-of-type(1)>tr:nth-of-type(1)>td:nth-of-type(5)>table:nth-of-type(1)>tbody:nth-of-type(1)'

但是使用bs4 .select()方法运行脚本时:

import requests
from bs4 import BeautifulSoup
import lxml

url = 'https://web.archive.org/web/19990421025223/http://www.rbc.ru'
headers = {
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
    }
r = requests.get(url, headers=headers)
soup = BeautifulSoup(r.content, 'lxml')
selector = 'body > table:nth-of-type(2) > tbody:nth-of-type(1)>tr:nth-of-type(1)>td:nth-of-type(5)>table:nth-of-type(1)>tbody:nth-of-type(1)'
print(soup.select(selector=selector))

输出为:[]-由于它由浏览器中的html代码组成,因此与预期的结果非常不同。

我在这里想念什么?

3 个答案:

答案 0 :(得分:1)

当用Python代码下载页面时,您不可能期望浏览器生成的选择器在BeautifulSoup中可靠地工作,因为在浏览器中呈现页面时,标记会更改。 ,没有渲染,您只会得到最初的未渲染HTML页面。

在这里,您必须提出自己的CSS选择器或其他方法来定位table元素。

由于页面的标记并非真正适合HTML解析,因此我通过其列名之一找到了一个table元素:

table = soup.find("b", text="спрос").find_parent("table")

请注意,只有当我用宽大的html5lib parser解析页面时,它才对我有用:

soup = BeautifulSoup(response.content, "html5lib")

答案 1 :(得分:0)

由于JavaScript在运行时可以呈现与源页面不同的整个页面,因此bs4对于动态更改的网站不利。

我建议使用Selenium,因为它实际上会打开网站,并且允许您在呈现某些元素之前暂停搜索。如果您不希望弹出浏览器,那么还有其他无头浏览器库可以静默地模拟浏览器环境。

答案 2 :(得分:0)

您的代码中有2个问题,首先,在BeautifulSoup中,如果要使用CSS选择器,则符号+ > ~必须用space隔开,如果需要,请参见here补丁bs4。

第二,作为我先前对your questions的回答,页面源中没有tbody,它是由浏览器生成的。

这里是固定的CSS选择器

selector = 'body > table:nth-of-type(2) > tr:nth-of-type(1) > td:nth-of-type(5) > table:nth-of-type(1)'