Python 3.4:LXML 网页抓取

Python 3.4 : LXML web scraping

我正在使用以下代码尝试 return 该网站上的代码列表。代码的结果是一个空列表。我从 google chromium 开发者工具中复制了 xpath。我究竟做错了什么?

from lxml import html
import requests


url = 'http://en.wikipedia.org/wiki/List_of_S%26P_500_companies'

resp = requests.get(url)
tree = html.fromstring(resp.text)

tickers = tree.xpath(r'//*[@id="mw-content-text"]/table[1]/tbody/tr[1]/td[1]/a')

print(tickers)

浏览器添加缺失的 HTML 元素,HTML 规范声明这些元素是模型的一部分。 lxml 不添加那些。

最常见的此类元素是 <tbody> 元素。您的文档没有这样的元素,但是 Chrome 有并且他们把它放在您的 XPath 中。 <thead>元素中的另一个这样的元素;同样,原来的 HTML 缺少它,但是 Chrome 把它放进去,并把 <tr> 行中的 <th> 个元素放在里面。

因此 正确的 XPath 表达式是:

tickers = tree.xpath(r'//*[@id="mw-content-text"]/table[1]/tr[2]/td[1]/a')

例如table 中的第二行,该行中的第一个 table 单元格。

注意lxml可以直接加载网址;在这种特定情况下,您真的不需要使用 requests

>>> from lxml import html
>>> url = 'http://en.wikipedia.org/wiki/List_of_S%26P_500_companies'
>>> tree = html.parse(url)
>>> tree.xpath(r'//*[@id="mw-content-text"]/table[1]/tr[2]/td[1]/a')
[<Element a at 0x10445e628>]
>>> tree.xpath(r'//*[@id="mw-content-text"]/table[1]/tr[2]/td[1]/a')[0].text
'MMM'
>>> tree.xpath(r'//*[@id="mw-content-text"]/table[1]/tr[2]/td[1]/a')[0].attrib['href']
'https://www.nyse.com/quote/XNYS:MMM'

如果您想提取第一列中的所有 <a> 元素,则必须删除对 <tr> 元素的限制;你的 XPath 选择全部,删除 [1] 到 select all:

links = tree.xpath(r'//*[@id="mw-content-text"]/table[1]/tr/td[1]/a')
for link in links:
    print(link.text, link.attrib['href'])