【问题标题】:Xpath with lxml returns empty string, selenium works ok带有lxml的Xpath返回空字符串,硒工作正常
【发布时间】:2019-04-29 16:06:29
【问题描述】:

我使用seleniumfind_element_by_xpath 从网页中提取一些文本。我已经设法在我的笔记本电脑上成功地完成了这项工作。但是,我需要在 Google Colab 中运行代码 所以我不能使用 selenium(Colab 中没有 Firefox 或 Chrome,我得到一个 geckodriver 错误,这是有道理的)。 lxml 看起来很有希望,我已经设法让它在几个值上起作用,但是 某些值不在提取的 html 中(奇怪),因此返回的字符串为空。

在其中一个 xpath 中删除“tbody”在一种情况下会有所帮助,根据这个 SO 答案:Python lxml - returns null list 但随后有几个单元格(如游戏日期)返回为空。

这适用于带有硒的笔记本电脑(来自 Firefox 的 XPATH):

from selenium import webdriver

URL = 'https://www.soccer24.com/match/C4RB2hO0/#match-summary'

browser = webdriver.Firefox()
browser.get(URL)

Selenium_TeamA_working = browser.find_element_by_xpath('/html/body/div[1]/div[1]/div[2]/table/tbody/tr/td[2]/table/tbody/tr[1]/td[1]/span/a').text
print('Team A using selenium: ' + Selenium_TeamA_working)           

这种方法适用于 LXML,但对某些值返回 NULL(来自 Chrome 的 XPATH)

import requests
from lxml import html

pageContent=requests.get(URL)
tree = html.fromstring(pageContent.content)
print(pageContent.content) #just to check the html string

TeamA_broken = tree.xpath('//*[@id="flashscore_column"]/table/tbody/tr[1]/td[1]/span/a/text()') #get Team A: this does not work
print('Team A using lxml (empty): ' + TeamA_broken) #output []
TeamA_working = tree.xpath('//*[@id="flashscore_column"]/table/tr[1]/td[1]/span/a/text()') #get Team A: drop tbody and then it works
print('Team A using lxml (working): ' + TeamA_working) #output ['Hull']
Date_notworking = tree.xpath('//*[@id="utime"]/text()') #this does not work and the game date is empty in the html
print('Game date using lxml (empty): ' + Date_notworking) #output []

我可以让 lxml 来提供我所拥有的 selenium 吗?

【问题讨论】:

  • 如果删除 tbody 有帮助,这意味着 lxml 不在 html5 模式下,而 Firefox 始终是。你可以试试 html5 解析器。

标签: python selenium xpath lxml


【解决方案1】:

那是因为在页面源 td@id="utime" 中确实是空的。该值来自script 节点中声明的变量,它看起来像var game_utime = 1495375200;。并不是说这是纪元时间,它可以转换为人类日期和时间May 21, 2017 5:00:00 PM

您可以使用正则表达式解析script节点并提取纪元时间,然后将其转换为所需的格式,如下所示

import time
import requests
from lxml import html
import re

pageContent = requests.get(URL).text

epoch_time =  re.search('var game_utime = (\d+);', pageContent).group(1)
date = time.strftime('%d-%m-%Y %H:%M', time.localtime(int(epoch_time)))
print(date)
#  21-05-2017 17:00

【讨论】:

  • 非常感谢!我仍然不知道如何为 A 队提取例如下半场得分 '1' (//*[@id="parts"]/tbody/tr[6]/td[2]/span[1 ]) 或 '4' 对于团队 B (//*[@id="parts"]/tbody/tr[6]/td[2]/span[2])。希望如果我破解这两个,我正在努力提取的许多其他内容将到位(如赔率、替代名称等)。我显然错过了一些东西。
  • @GivenX ,这些数据(游戏统计数据)似乎来自 XHR 到 d.soccer24.com/x/feed/d_su_C4RB2hO0_en_2,但目前我看不出这两个请求如何连接......但是,等等,C4RB2hO0它只是一个游戏标识符,因此您可以使用 URL 模板 url = "https://d.soccer24.com/x/feed/d_su_{}_en_2" 并传递游戏 ID:url.format('C4RB2hO0')
  • 好的,我所要做的就是保存 html,然后将其读回,一切正常,无需对日期进行任何操作,所有其他值都可以通过 xpath 访问。
  • with open(r'HUL 1-7 TOT _ Hull - Tottenham _ Match Summary.html', "r") as f: page = f.read() tree = html.fromstring(page) output = tree.xpath('//*[@id="utime"]/text()') print(output)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-03
  • 2015-07-05
相关资源
最近更新 更多