【问题标题】:Python and xpath: identify html tags with spaced attributesPython和xpath:识别带有间隔属性的html标签
【发布时间】:2018-06-25 11:56:07
【问题描述】:

考虑以下代码:

<div class="tag1">
<div>
    <a class="tag11 tag12" href="http://www.example.com/file1" title="file1"><img class="tag2" src="http://www.example.com/img1.jpg" alt="textalt">linktext</a>
    <span class="tag3">.</span>
</div>

<div>
    <a class="tag11 tag12" href="http://www.example.com/file2" title="file2"><img class="tag2" src="http://www.example.com/img1.jpg" alt="textalt">linktext</a>
    <span class="tag3">.</span>
</div>

这是一个较大的 html 页面的 部分,其中包含带有其他标签的其他 a 元素。但是,我想only 引用类为tag11 tag12a 元素,并创建一个包含所有href 值的列表。 tag11tag12 之间有一个空格。

使用 Python 3.5、lxmlxpath,这是第一次尝试:

from lxml import html
import requests

page = requests.get('http://www.example.com/page.html')
tree = html.fromstring(page.content)

atest = tree.xpath('//a[contains(@class='tag11 tag12')]')

但它不起作用。使用单个顶点:

File "<stdin>", line 1
    buyers = tree.xpath('//a[contains(@class='tag11 tag12')]')
                                                  ^
SyntaxError: invalid syntax

使用双顶点:

tree.xpath('//a[contains(@class="tag11 tag12")]')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "src/lxml/lxml.etree.pyx", line 1587, in lxml.etree._Element.xpath (src/lxml/lxml.etree.c:61854)
  File "src/lxml/xpath.pxi", line 307, in lxml.etree.XPathElementEvaluator.__call__ (src/lxml/lxml.etree.c:178516)
  File "src/lxml/xpath.pxi", line 227, in lxml.etree._XPathEvaluatorBase._handle_result (src/lxml/lxml.etree.c:177421)
lxml.etree.XPathEvalError: Invalid number of arguments

另外(来自this answer):

atest = tree.xpath('//a[contains(@class, "tag11") and contains(@class, "tag12")]')

得到一个空的atest列表。

如何正确处理class标签中包含空格的a元素?


我正在使用 Python 3.5、lxmlxpath,因为我正在尝试学习这些工具。因此,没有特别的理由不使用 BeautifulSoup,但我只是在为这些列出的工具寻找特定的解决方案,如果有的话。

【问题讨论】:

  • 我不是 Python 开发人员,但您可能需要转义单引号。你试过'//a[@class = \'tag11 tag12\']' 吗?或tree.xpath('//a[contains(@class, \'tag11\') and contains(@class, \'tag12\')]')
  • @derloopkat 谢谢。第一个产生错误;第二个创建(我猜)原始元素列表:[&lt;Element a at 0x7f3a47b5c6d8&gt;, &lt;Element a at 0x7f3a440e2818&gt;]。不是实际的 href 字符串。

标签: html python-3.x xpath web-scraping lxml


【解决方案1】:

是否有不使用 BeautifulSoup4 的理由?这是我项目中的代码 sn-p:

import urllib.request             # You could use requests library as well   
from bs4 import BeautifulSoup

url = 'http://www.example.com/page.html'
header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
         "AppleWebKit/537.36 (KHTML, like Gecko)"
         "Chrome/67.0.3396.87 Safari/537.36"}

soup = BeautifulSoup(urllib.request.urlopen(
                     urllib.request.Request(url, headers=header)),
                     'lxml')

links = list()
for link in soup.find_all('a', class_='tag1 tag2'):
    links.append(link.get('href'))

【讨论】:

  • 我编辑了这个问题,希望能回答你的问题。不过,感谢您提供替代解决方案。
【解决方案2】:

检查这个 XPath:'//a[@class="tag11 tag12"]/@href'

from lxml import html

page = "<div class=\"tag1\"> <div> <a class=\"tag11 tag12\" href=\"http://www.example.com/file1\" title=\"file1\"><img class=\"tag2\" src=\"http://www.example.com/img1.jpg\" alt=\"textalt\">linktext</a> <span class=\"tag3\">.</span> </div> <div> <a class=\"tag11 tag12\" href=\"http://www.example.com/file2\" title=\"file2\"><img class=\"tag2\" src=\"http://www.example.com/img1.jpg\" alt=\"textalt\">linktext</a> <span class=\"tag3\">.</span> </div>"
tree = html.fromstring(page)
links = tree.xpath('//a[@class="tag11 tag12"]/@href')

for link in links:
    print(link)

输出:

http://www.example.com/file1
http://www.example.com/file2

【讨论】:

    【解决方案3】:

    尝试以下方法来玩多个类。如果classes 都存在,它将返回所需的输出:

    from lxml.html import fromstring
    
    content = """
    <div class="tag1">
    <div>
        <a class="tag11 tag12" href="http://www.example.com/file1" title="file1"><img class="tag2" src="http://www.example.com/img1.jpg" alt="textalt">linktext</a>
        <span class="tag3">.</span>
    </div>
    
    <div>
        <a class="tag11 tag12" href="http://www.example.com/file2" title="file2"><img class="tag2" src="http://www.example.com/img1.jpg" alt="textalt">linktext</a>
        <span class="tag3">.</span>
    </div>
    """
    tree = fromstring(content)
    for atest in tree.xpath('//a[contains(@class, "tag11") and contains(@class, "tag12")]'):
        print(atest.attrib['href'])
    

    输出:

    http://www.example.com/file1
    http://www.example.com/file2
    

    【讨论】:

    • 我的目标是“如何正确处理a 元素,其class 标记包含空格”,在html 页面中有xpath。我试图将问题编辑得更清楚并提供更多背景信息。
    • 仅供参考,切勿在单个表达式中使用multiple classes(您提到的以空格分隔),因为一个或多个类可能会动态生成,并且您的表达式很容易中断。这里更安全的方法是使用contains() 关键字,正如我在上面尝试显示的那样。谢谢。
    • 是的,我已在其他帖子中阅读过此建议。在这种特殊情况下,由于不是页面的所有者,我无法纠正这个缺陷。如果我理解正确,您的方法将 所有 a 元素标识为 multiple classes,但在我的情况下,只有 tag11 tag12 的元素必须列出。
    猜你喜欢
    • 1970-01-01
    • 2018-10-16
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    • 2016-07-20
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    相关资源
    最近更新 更多