【问题标题】:How to return result as HTML with HtmlXPathSelector (Scrapy)如何使用 HtmlXPathSelector (Scrapy) 以 HTML 形式返回结果
【发布时间】:2012-07-13 02:57:13
【问题描述】:

如何检索标签中包含的所有 HTML?

hxs = HtmlXPathSelector(response)
element = hxs.select('//span[@class="title"]/')

也许是这样的:

hxs.select('//span[@class="title"]/html()')

编辑: 如果我查看documentation,我只会看到返回新XPathSelectorList 的方法,或者只是标签内的原始文本。 我想检索的不是新列表或文本,而是标签内的 源代码 HTML。 例如:

<html>
    <head>
        <title></title>
    </head>
    <body>
        <div id="leexample">
            justtext
            <p class="ihatelookingforfeatures">
                sometext
            </p>
            <p class="yahc">
                sometext
            </p>
        </div>
        <div id="lenot">
            blabla
        </div>
    an awfuly long example for this.
    </body>
</html>

我想做一个像hxs.select('//div[@id="leexample"]/html()') 这样的方法,它会返回它里面的HTML,像这样:

justtext
<p class="ihatelookingforfeatures">
    sometext
</p>
<p class="yahc">
    sometext
</p>

我希望我消除了围绕我的问题的歧义。

如何在 Scrapy 中从 HtmlXPathSelector 获取 HTML? (也许是scrapy范围之外的解决方案?)

【问题讨论】:

  • “检索所有 HTML” 是什么意思?你需要展示一个例子。
  • 我最初的想法是递归遍历标签内的所有标签,将它们复制为 html,但这太复杂了,一定有人想到了更简单的东西..

标签: python xpath scrapy


【解决方案1】:

在您的XpathSelectorList 上致电.extract()。它应该返回一个包含你想要的 HTML 内容的 unicode 字符串列表。

hxs.select('//div[@id="leexample"]/*').extract()

更新

# This is wrong
hxs.select('//div[@id="leexample"]/html()').extract()

/html() 不是有效的 scrapy 选择器。要提取所有孩子,请使用'//div[@id="leexample"]/*''//div[@id="leexample"]/node()'。请注意,node() 将返回 textNode,结果类似于:

[u'\n', u'&lta href="image1.html">名称:我的图片 1
' ]

【讨论】:

  • /html() 不受支持,我什至不确定它是否有效。 Scrapy 会抛出:ValueError: Invalid XPath: //h1/html()
【解决方案2】:

使用

//span[@class="title"]/node()

这会选择所有节点(元素、文本节点、处理指令和 cmets),它们是 XML 文档中 class 属性值为 "title" 的任何 span 元素的子节点。

如果您只想获取文档中第一个这样的span 的子节点,请使用

(//span[@class="title"])[1]/node()

【讨论】:

  • 很好,但不是我要求的。它返回一个元素列表-> 我需要这些元素后面的 HTML。不是节点 => 纯 HTML。
  • @Saga:这不能用 XPath 完成——你需要在托管 XPath 的编程语言中使用特定的 DOM 方法/属性(例如 OuterXMLInnerXml —— 或者这些可以命名为 OuterHtml / InnerHtml -- 或者在其他 DOM 中 -- node.Save())
  • 注意:如果有多个类,//span[@class="title"]/node() 将失败。将它与 css 选择器连接以选择具有给定类的元素:parent.css('.title').xpath('node()')
  • @Kangur,不需要 CSS。请参阅此答案,解释如何确定一个元素有一个类,该类可能与其他类名一起出现:stackoverflow.com/a/35354908/36305
【解决方案3】:

虽然晚了,但我还是把这个留作记录。

我做的是:

html = ''.join(hxs.select('//span[@class="title"]/node()').extract())

或者如果我们要匹配各种节点:

elements = hxs.select('//span[@class="title"]')
html = [''.join(e) for e in elements.select('./node()')]

【讨论】:

    【解决方案4】:

    类似于@xiaowl 指出的, 使用 hxs.select('//div[@id="leexample"]').extract() 将检索从 xPath 查询中检索到的标记的所有 HTML 内容://div[@id="leexample"]

    所以为了记录,我最终得到了;

    post = postItem() #body = Field #/in item.py
    post['body'] = hxs.select('//span[@id="edit' + self.postid+ '"]').extract()
    open('logs/test.log', 'wb').write(str(post['body']))
    #logs.test.log contains all the HTML inside the tag selected by the query.
    

    【讨论】:

    • 如果 xiaowl 的回答有帮助,请接受/点赞他的回答。
    【解决方案5】:

    实际上并不像看起来那么难。只需删除 XPath 查询的最后 / ,并使用 extract() 方法。我在scrapy shell 中运行了一个示例,这是一个缩短版:

    sjaak:~ sjaakt$ scrapy shell
    2012-07-19 11:06:21+0200 [scrapy] INFO: Scrapy 0.14.4 started (bot: scrapybot)
    >>> fetch('http://www.nu.nl')
    2012-07-19 11:06:34+0200 [default] INFO: Spider opened
    2012-07-19 11:06:34+0200 [default] DEBUG: Crawled (200) <GET http://www.nu.nl> (referer: None)
    >>> hxs.select("//h1").extract()
    [u'<h1>    <script type="text/javascript">document.write(NU.today())</script>.\n    Het laatste nieuws het eerst op NU.nl    </h1>\n    ']
    >>> 
    

    要仅获取标记的内部内容,请在 XPath 查询中使用添加 /*。示例:

    >>> hxs.select("//h1/*").extract()
    [u'<script type="text/javascript">document.write(NU.today())</script>.\n    Het laatste nieuws het eerst op NU.nl    ']
    

    【讨论】:

      【解决方案6】:

      一点黑客攻击(进入私有财产 _rootSelector,在 1.0.5 中工作):

      from lxml import html
      def extract_inner_html(sel):
          return (sel._root.text or '') + ''.join([html.tostring(child) for child in sel._root.iterdescendants()])
      
      def extract_inner_text(sel):
          return (''.join(sel.css('::text').extract())).strip()
      

      像这样使用它:

      reason = extract_inner_html(statement.css(".politic-rating .rate-reason")[0])
      text = extract_inner_text(statement.css('.politic-statement')[0])
      all_text = extract_inner_text(statement.css('.politic-statement'))
      

      我找到了 lxml 代码部分 in this question

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-21
        • 1970-01-01
        • 2021-01-08
        • 1970-01-01
        • 2015-07-13
        • 1970-01-01
        • 1970-01-01
        • 2021-05-01
        相关资源
        最近更新 更多