使用Python和lxml

时间:2016-02-02 21:11:42

标签: python html lxml

我正在尝试让python从网站的某个位置提取文本。我已经确定了HTML div:

<div class="number">76</div>

位于:

...div/div[1]/div/div[2]

我正在尝试使用lxml从中提取'76',但除了以下内容之外无法获得退出: []

这是我的代码:

from lxml import html
import requests
url = 'https://sleepiq.sleepnumber.com/#/#@1'
values = {'username': 'my@gmail.com',
          'password': 'mypassword'}

page = requests.get(url, data=values)
tree = html.fromstring(page.content)
hr = tree.xpath('//div[@class="number"]/text()')
print hr

有什么建议吗?我觉得这应该很简单,提前谢谢!

更新:我想要的元素不包含在page.content

requests.get

更新的更新:看起来这不是我登录到我想要的内容的页面。它只获取登录屏幕内容。

3 个答案:

答案 0 :(得分:3)

您是否尝试过打印page.content以确保requests.get正在检索您想要的内容?这通常是事情破裂的地方。并且您的空列表从xpath搜索结果返回,表示未找到。&#34;

假设没问题,你的解析就很接近了。我刚刚尝试了以下,这是成功的:

from lxml import html

tree = html.fromstring('<body><div class="number">76</div></body>')
number = tree.xpath('//div[@class="number"]/text()')[0]

number现在等于'76'。请注意[0]索引,因为xpath始终会返回找到的内容列表。您必须取消引用才能找到内容。

这里常见的问题是XPath text()函数并不像它看起来那样具有包容性或直接性。如果div有任何子元素 - 例如。如果文本真的是<div class="number"><strong>76</strong></div>,那么text()将返回一个空列表,因为该文本属于strong而非div。在现实世界的HTML中 - 尤其是从文字处理器剪切和粘贴的HTML,或者人类编辑的HTML - 这些额外的元素是完全常见的。

虽然它不能解决所有已知的文本管理问题,但一个方便的解决方法是使用//多级间接而不是/单级间接来发送文本:

number = ''.join(tree.xpath('//div[@class="number"]//text()'))

现在,无论是否存在子元素,总文本将被连接并返回。

更新好的,如果您的问题是登录的,您可能希望至少尝试requests.post(而不是.get)。在更简单的情况下,这种改变可能会起作用。在其他情况下,登录需要完成一个单独的页面而不是您要检索/ scape的页面。在这种情况下,您可能希望使用会话对象:

with requests.Session() as session:
    # First POST to the login page
    landing_page = session.post(login_url, data=values)

    # Now make authenticated request within the session
    page = session.get(url)
    # ...use page as above...

这有点复杂,但显示了单独登录页面的逻辑。许多网站(例如WordPress网站)都需要这样做。在身份验证后,他们经常会将您带到不是有趣内容的页面(如网站主页)(尽管可以抓取以确定登录是否成功)。这种改变的登录工作流程不会改变任何解析技术,如上所述。

答案 1 :(得分:2)

答案 2 :(得分:1)

在这种情况下,我会使用普通正则表达式而不是xml工具。它更容易处理。

import re
import requests

url = 'http://sleepiq.sleepnumber.com/#/user/-9223372029758346943#@2'
values = {'email-email': 'my@gmail.com', 'password-clear': 'Combination',
          'password-password': 'mypassword'}

page = requests.get(url, data=values, timeout=5)
m = re.search(r'(\w*)(<div class="number">)(.*)(<\/div>)', page.content)
# m = re.search(r'(\w*)(<title>)(.*)(<\/title>)', page.content)

if m:
    print(m.group(3))
else:
    print('Not found')