问题描述
嗨,我想从这个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)时,它只返回一个空列表,这意味着我使用的标签错误。
解决方法
如果您替换:
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")
您得到了我想找的东西。此处的主要更改是用子代选择器(parent > child
)替换子选择器(ancestor descendant
),这对于中间内容的外观要宽容得多。
更新:这很有趣。您选择的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>
标签都会导致文档结构解析异常。
这是此问题的解决方案:
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)
基本上,您尝试提取文本的方式不正确,因为每个电影名称锚标记的选择器都不同。
,这应该有效:
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)