【问题标题】:Select li elements from ul with xpath使用 xpath 从 ul 中选择 li 元素
【发布时间】:2019-02-05 02:42:06
【问题描述】:

我从lxmlPython3XPATH 开始,我无法获得正确的sintaxis 来选择所有li 内容为ul 的元素。我正在尝试这种结构:

<body>
 <div> ..... </div>
 <div> ..... </div>
 <div id="div-A">
  <div id="subdiv-1">
   <form> ... </form>
   <div> ..... </div>
   <div> ..... </div>
   <ul>
    <li>
     <div id="div-1">
      <div> ..... </div>
      <div> ..... </div>
      <div id="subdiv-1">
       <a class="name">
        <span>
          ....text1....
        </span>
       </a>
      </div>
      <div id="subdiv-2">
       <div class="class-1">
        <div class="subClass-1">
         <div> ....text2.... </div>
        </div>
        <span class="subClass-2">
         ....text3....
        </span>
       </div>
      </div>
     </div>
    </li>
    ... x23...
   </ul>
  </div>
 </div>
</body>

我的目标是能够获得 text1text2text3

首先,我尝试获取所有 li 元素及其内容:

content = html_response.content
fixed_content = fromstring(content)  # parse the HTML and correct malformed HTML
items = fixed_content.xpath('//ul/li/*')

然后将items 传递给带有for 循环的函数,以遍历23 个li 元素。现在我尝试获取文本,所以:

for item in items:
 text1 = item.xpath('/div[@id="div-1"]/div[@id="subdiv-1"]/a[@class="name"]/span').text_content()
 text2 = item.xpath('/div[@id="div-1"]/div[@id="subdiv-2"]/div[@class="class-1"]/div[@class="subClass-1"]/div').text_content()
 text3 = item.xpath('/div[@id="div-1"]/div[@id="subdiv-2"]/div[@class="class-1"]/div[@class="subClass-2"]/span[@class="subClass-2"]').text_content()

但我在所有情况下都得到一个没有内容的空结果。我做错了什么?

问候。

【问题讨论】:

    标签: html python-3.x xpath lxml


    【解决方案1】:

    尝试以下代码以获得所需的输出:

    items = fixed_content.xpath('//ul/li//span | //ul/li//div[@class="subClass-1"]')
    for item in items:
        item.text_content().strip()
    

    输出是

    '....text1....'
    '....text2....'
    '....text3....'
    

    items = fixed_content.xpath('//ul/li') 
    for item in items:
        text1 = item.xpath('.//a[@class="name"]/span')[0].text_content().strip()
        text2 = item.xpath('.//div[@class="subClass-1"]')[0].text_content().strip()
        text3 = item.xpath('.//span[@class="subClass-2"]')[0].text_content().strip()
    

    如果要将每个文本节点作为变量获取

    【讨论】:

    • 谢谢,所以我的错误是在 '//ul/li/*' 上,而不是从 "xpath('." 上的点开始 :)
    • '//ul/li/*' 应该选择li 节点的所有子节点,而不是li 节点。如果 XPath 以点开头,则意味着您要搜索当前节点的子/后代(在您的情况下为 item),而没有点则意味着在整个 HTML DOM 中搜索...
    • 感谢您的解释!
    【解决方案2】:

    您的 xpath 查询似乎为我提供了想要的输出。 text1、text2 和 text3 完全写出时的结果。使用 string() 方法,您可以选择找到的元素的内部文本值:

    //ul/li/div[@id="div-1"]/div[@id="subdiv-1"]/a[@class="name"]/span/string(),
    //ul/li/div[@id="div-1"]/div[@id="subdiv-2"]/div[@class="class-1"]/div[@class="subClass-1"]/div/string(),
    //ul/li/div[@id="div-1"]/div[@id="subdiv-2"]/div[@class="class-1"]/span[@class="subClass-2"]/string()
    

    写出它们并使用 string() 方法不会为您提供预期的 text1-3 值吗?

    【讨论】:

    • 是的,但我认为我的问题是没有立即执行字符串。我有 '//ul/li/*' 而不是 '//ul/li' 并且在 for 循环中,我没有像 Andersson 指出的那样以点“xpath('.”开头。无论如何感谢您的回答: )
    • 啊,我明白了,我的错。很高兴你确实解决了它! :)
    【解决方案3】:
    [i.strip() for i in tree.xpath('//ul//div[@class="subClass-1"]//text()|//ul//span//text()') if i.strip()]
    

    【讨论】:

    • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
    猜你喜欢
    • 2021-07-03
    • 2019-08-15
    • 2016-05-19
    • 1970-01-01
    • 1970-01-01
    • 2015-06-26
    • 1970-01-01
    • 2020-02-01
    • 2022-12-05
    相关资源
    最近更新 更多