为什么这个 XPath 不起作用?
Why isn't this XPath working?
我正在尝试获取股票的公司名称、部门和行业。我为 'https://finance.yahoo.com/q/in?s={}+Industry'.format(sign)
下载 HTML,然后尝试使用 lxml.html
的 .xpath()
解析它。
为了获取我要抓取的数据的 XPath,我转到 Chrome 中的站点,右键单击该项目,单击 Inspect Element
,右键单击突出显示的区域,然后单击 Copy XPath
。这在过去一直对我有用。
可以使用以下代码重现此问题(我以 Apple 为例):
import requests
from lxml import html
page_p = 'https://finance.yahoo.com/q/in?s=AAPL+Industry'
name_p = '//*[@id="yfi_rt_quote_summary"]/div[1]/div/h2/text()'
sect_p = '//*[@id="yfncsumtab"]/tbody/tr[2]/td[1]/table[2]/tbody/tr/td/table/tbody/tr[1]/td/a/text()'
indu_p = '//*[@id="yfncsumtab"]/tbody/tr[2]/td[1]/table[2]/tbody/tr/td/table/tbody/tr[2]/td/a/text()'
page = requests.get(page_p)
tree = html.fromstring(page.text)
name = tree.xpath(name_p)
sect = tree.xpath(sect_p)
indu = tree.xpath(indu_p)
print('Name: {}\nSector: {}\nIndustry: {}'.format(name, sect, indu))
这给出了这个输出:
Name: ['Apple Inc. (AAPL)']
Sector: []
Industry: []
它没有遇到任何下载困难,因为它能够检索 name
,但其他两个不起作用。如果我分别用 tr[1]/td/a/text()
和 tr[1]/td/a/text()
替换它们的路径,它 returns this:
Name: ['Apple Inc. (AAPL)']
Sector: ['Consumer Goods', 'Industry Summary', 'Company List', 'Appliances', 'Recreational Goods, Other']
Industry: ['Electronic Equipment', 'Apple Inc.', 'AAPL', 'News', 'Industry Calendar', 'Home Furnishings & Fixtures', 'Sporting Goods']
显然,我可以只切出每个列表中的第一项来获取我需要的数据。
我不明白的是,当我将 tbody/
添加到开头时 (//tbody/tr[#]/td/a/text()
) 它再次失败,即使 Chrome 中的控制台清楚地显示了两个 tr
s 是 tbody
元素的子元素。
为什么会这样?
浏览器解析 HTML 并从中构建元素树;在此过程中,他们将插入输入 HTML 文档中可能缺失的元素。
在这种情况下,<tbody>
个元素 不在源 HTML 中。您的浏览器会插入它们,因为如果缺少它们,它们将隐含在结构中。但是 LXML 不会插入它们。
出于这个原因,您的浏览器工具不是构建 XPath 查询的最佳工具。
删除 tbody/
路径元素会产生您要查找的结果:
>>> sect_p = '//*[@id="yfncsumtab"]/tr[2]/td[1]/table[2]/tr/td/table/tr[1]/td/a/text()'
>>> indu_p = '//*[@id="yfncsumtab"]/tr[2]/td[1]/table[2]/tr/td/table/tr[2]/td/a/text()'
>>> tree.xpath(sect_p)
['Consumer Goods']
>>> tree.xpath(indu_p)
['Electronic Equipment']
我正在尝试获取股票的公司名称、部门和行业。我为 'https://finance.yahoo.com/q/in?s={}+Industry'.format(sign)
下载 HTML,然后尝试使用 lxml.html
的 .xpath()
解析它。
为了获取我要抓取的数据的 XPath,我转到 Chrome 中的站点,右键单击该项目,单击 Inspect Element
,右键单击突出显示的区域,然后单击 Copy XPath
。这在过去一直对我有用。
可以使用以下代码重现此问题(我以 Apple 为例):
import requests
from lxml import html
page_p = 'https://finance.yahoo.com/q/in?s=AAPL+Industry'
name_p = '//*[@id="yfi_rt_quote_summary"]/div[1]/div/h2/text()'
sect_p = '//*[@id="yfncsumtab"]/tbody/tr[2]/td[1]/table[2]/tbody/tr/td/table/tbody/tr[1]/td/a/text()'
indu_p = '//*[@id="yfncsumtab"]/tbody/tr[2]/td[1]/table[2]/tbody/tr/td/table/tbody/tr[2]/td/a/text()'
page = requests.get(page_p)
tree = html.fromstring(page.text)
name = tree.xpath(name_p)
sect = tree.xpath(sect_p)
indu = tree.xpath(indu_p)
print('Name: {}\nSector: {}\nIndustry: {}'.format(name, sect, indu))
这给出了这个输出:
Name: ['Apple Inc. (AAPL)']
Sector: []
Industry: []
它没有遇到任何下载困难,因为它能够检索 name
,但其他两个不起作用。如果我分别用 tr[1]/td/a/text()
和 tr[1]/td/a/text()
替换它们的路径,它 returns this:
Name: ['Apple Inc. (AAPL)']
Sector: ['Consumer Goods', 'Industry Summary', 'Company List', 'Appliances', 'Recreational Goods, Other']
Industry: ['Electronic Equipment', 'Apple Inc.', 'AAPL', 'News', 'Industry Calendar', 'Home Furnishings & Fixtures', 'Sporting Goods']
显然,我可以只切出每个列表中的第一项来获取我需要的数据。
我不明白的是,当我将 tbody/
添加到开头时 (//tbody/tr[#]/td/a/text()
) 它再次失败,即使 Chrome 中的控制台清楚地显示了两个 tr
s 是 tbody
元素的子元素。
为什么会这样?
浏览器解析 HTML 并从中构建元素树;在此过程中,他们将插入输入 HTML 文档中可能缺失的元素。
在这种情况下,<tbody>
个元素 不在源 HTML 中。您的浏览器会插入它们,因为如果缺少它们,它们将隐含在结构中。但是 LXML 不会插入它们。
出于这个原因,您的浏览器工具不是构建 XPath 查询的最佳工具。
删除 tbody/
路径元素会产生您要查找的结果:
>>> sect_p = '//*[@id="yfncsumtab"]/tr[2]/td[1]/table[2]/tr/td/table/tr[1]/td/a/text()'
>>> indu_p = '//*[@id="yfncsumtab"]/tr[2]/td[1]/table[2]/tr/td/table/tr[2]/td/a/text()'
>>> tree.xpath(sect_p)
['Consumer Goods']
>>> tree.xpath(indu_p)
['Electronic Equipment']