无法使用 css 选择器获取 python 中的数据

Can't use a css selector to get data in python

嗨,我想从中获取电影片名website

url = "https://www.the-numbers.com/market/" + "2019" + "/top-grossing-movies"
raw = requests.get(url, headers={'User-Agent':'Mozilla/5.0'})  
html = BeautifulSoup(raw.text, "html.parser")
movie_list = html.select("#page_filling_chart > table > tbody > tr > td > b > a")
for i in range(len(movie_list)):
    print(movie_list[i].text)

我收到了 200 的响应,抓取其他信息也没有问题。但问题出在变量 movie_list.

当我打印(movie_list)时,它returns只是一个空列表,这意味着我使用了错误的标签。

下面是这个问题的解答:

from bs4 import BeautifulSoup
import requests

url = "https://www.the-numbers.com/market/" + "2019" + "/top-grossing-movies"
raw = requests.get(url, headers={'User-Agent':'Mozilla/5.0'})  
html = BeautifulSoup(raw.text, "html.parser")
movie_table_rows = html.findAll("table")[0].findAll('tr')

movie_list = []
for tr in movie_table_rows[1:]:
    tds = tr.findAll('td')
    movie_list.append(tds[1].text) #Extract Movie Names

print(movie_list)

基本上,您尝试提取文本的方式不正确,因为每个电影名称锚标记的选择器都不同。

如果你替换:

movie_list = html.select("#page_filling_chart > table > tbody > tr > td > b > a")

有:

movie_list = html.select("#page_filling_chart table tr > td > b > a")

你得到了我认为你正在寻找的东西。此处的主要更改是用后代选择器 (ancestor descendant) 替换 child-selectors (parent > child),这对于中间内容的外观而言更加宽容。


更新:这很有趣。您选择的 BeautifulSoup 解析器似乎会导致不同的行为。

比较:

>>> html = BeautifulSoup(raw, 'html.parser')
>>> html.select('#page_filling_chart > table')
[]

有:

>>> html = BeautifulSoup(raw, 'lxml')
>>> html.select('#page_filling_chart > table')
[<table>
<tr><th>Rank</th><th>Movie</th><th>Release<br/>Date</th><th>Distributor</th><th>Genre</th><th>2019 Gross</th><th>Tickets Sold</th></tr>
<tr>
[...]

事实上,使用 lxml 解析器,您可以 几乎 使用您原来的选择器。这有效:

html.select("#page_filling_chart > table > tr > td > b > a"

经过解析,一个table没有tbody.

稍作试验后,您必须像这样重写原始查询才能使其与 html.parser:

一起使用
html.select("#page_filling_chart2 > p > p > p > p > p > table > tr > td > b > a")

看起来 html.parser 没有合成关闭的 </p> 元素,当它们从源中丢失时,所以所有未关闭的 <p> 标签导致一个奇怪的解析文档结构。

这应该有效:

url = 'https://www.the-numbers.com/market/2019/top-grossing-movies'
raw = requests.get(url)  
html = BeautifulSoup(raw.text, "html.parser")
movie_list = html.select("table > tr > td > b > a")
for i in range(len(movie_list)):
    print(movie_list[i].text)