【问题标题】:python: xpath returns empty list from boxofficemojo.compython:xpath 从 boxofficemojo.com 返回空列表
【发布时间】:2016-01-20 05:48:39
【问题描述】:

我正在尝试使用以下代码从 BoxOfficeMojo.com 上每部电影的页面中抓取特定数据。不幸的是,xpath 返回一个空列表。一些帖子建议从 xpath 中删除 tbody,但这也会返回一个空列表。我使用相同的代码从烂番茄和 IMBD 中提取文本,并且 xpath 运行良好。有谁知道为什么会发生这种情况以及如何解决?

from lxml import html
import requests

# Box Office Mojo Scrape
page = requests.get('http://www.boxofficemojo.com/movies/?page=main&id=ateam.htm')
tree = html.fromstring(page.text)

print tree.xpath('//*[@id="body"]/table[2]/tbody/tr/td/table[1]/tbody/tr/td[2]/table/tbody/tr/td/center/table/tbody/tr[1]/td/font/b/text()')
print tree.xpath('//*[@id="body"]/table[2]/tr/td/table[1]/tr/td[2]/table/tr/td/center/table/tr[1]/td/font/b/text()')

# Rotten Tomatoes Scrape
page2 = requests.get('http://www.rottentomatoes.com/m/star_wars_episode_vii_the_force_awakens/')
tree2 = html.fromstring(page2.text)

print tree2.xpath('//*[@id="scorePanel"]/div[2]/div[1]/a/div/div[2]/div[1]/span/text()')

# IMDB Scrape
page3 = requests.get('http://www.imdb.com/title/tt2488496/?ref_=nv_sr_1')
tree3 = html.fromstring(page3.text)

print tree3.xpath('//*[@id="overview-top"]/h1/span[1]/text()')

【问题讨论】:

  • 您需要告诉我们更多您想要为我们提供帮助的内容。然而,即使没有告诉我们你在追求什么,我也能看出一个问题。 id 为 body 的元素仅包含一个表,其他所有内容都在该表中,但您要求的是该 div 下的第二个表。由于只有一个表,因此您将获得一个空节点集。因此,您的问题出现在您的位置路径 //*[@id="body"]/table[2] 的开头。
  • @Matthew 我试图在第一个表中提取“国内总毛”值:77,222,099 美元。我不确定只有一张桌子是什么意思。当我检查 html 树时,
    . 下有几个表
  • 其他表包含在 body div 中的单个表中。

标签: python xpath


【解决方案1】:

包含所需信息的表格嵌套在另一个表格中,依此类推。因此,尝试获取 //*[@id='body']/table[2] 是行不通的,因为该 div 中只有一个表(其中嵌套了其他表)。

您可以使用极其笨拙的 xpath 表达式来获得它

//*[@id='body']/table/tr[2]/table/tr/td/table[1]/tr/td[2]/table/tr/td/center/table[1]/tr[1]/td/font/b/text()

请注意,所需信息包含在字体标签内的粗体标签内,文字Domestic Total Gross:直接位于字体内。我会使用以下内容来获取该信息

//*[@id='body']//font[starts-with(normalize-space(.),'Domestic Total Gross:')]/b/text()

如果表结构发生变化,这也不太脆弱。

【讨论】:

  • 谢谢!两者都工作得很好。后者更容易构建以获取更多信息(发行商、流派、预算等)。您是否知道任何可以更深入地了解如何构建这些类型的 xpath 的资源?例如,我还想提取前面没有文字的电影的标题(上例中的“The A-Team”)。
  • 要获得标题,您需要类似于上面的长格式的东西,因为没有什么更接近真正抓住,但同样,如果页面结构发生任何变化,风险很大。就个人而言,我会从页面标题中获取它。要以这种方式提取它,我们可以使用substring-before(/html/head/title,' - Box Office Mojo'),它给出了The A-Team (2010)。为了摆脱这一年,你可以在 python 中做额外的工作。
  • 网上应该有很多 XPath 教程。通常 XSLT 的资源也会提供很好的 Xpath 教程。您可以尝试tag wiki 中的一些链接以开始使用。
  • 您也可以使用tree.xpath("//*[@id='body']//font[string-length(normalize-space(text()))=0]/b/text()")[0] 获取标题,但同样,如果页面结构发生变化,这是有风险的。从页面标题抓取更加稳定。
  • 太好了,再次感谢!感谢您提出稳定的方法,因为我听说 boxofficemojo.com 倾向于改变他们网站的结构。我使用以下内容从页面标题中提取电影标题:tree.xpath(/html/head/title/text()) 如您所述。
猜你喜欢
相关资源
最近更新 更多
热门标签