如何从Scrapy选择器中提取原始html?

2024-05-01 19:37:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用response.xpath('//*')re_first()提取js数据,然后将其转换为python本地数据。问题是extract/re方法似乎不能提供不引用html的方法

原始html:

{my_fields:['O'Connor Park'], }

提取输出:

{my_fields:['O'Connor Park'], }

将此输出转换为json将不起作用。

最简单的办法是什么?


Tags: 数据方法rejsonparkfieldsresponsemy
3条回答

简短回答:

  • Scrapy/Parsel选择器.re().re_first()方法替换HTML实体(除了<&
  • 相反,使用.extract().extract_first()获取原始HTML(或原始JavaScript指令),并对提取的字符串使用Python的re模块

长答案:

让我们看一个示例输入和从HTML中提取Javascript数据的各种方法。

HTML示例:

<html lang="en">
<body>
<div>
    <script type="text/javascript">
        var i = {a:['O&#39;Connor Park']}
    </script>
</div>
</body>
</html>

使用scrapy选择器(它使用下面的parsel库),您可以使用多种方法提取Javascript片段:

>>> import scrapy
>>> t = """<html lang="en">
... <body>
... <div>
...     <script type="text/javascript">
...         var i = {a:['O&#39;Connor Park']}
...     </script>
...     
... </div>
... </body>
... </html>
... """
>>> selector = scrapy.Selector(text=t, type="html")
>>> 
>>> # extracting the <script> element as raw HTML
>>> selector.xpath('//div/script').extract_first()
u'<script type="text/javascript">\n        var i = {a:[\'O&#39;Connor Park\']}\n    </script>'
>>> 
>>> # only getting the text node inside the <script> element
>>> selector.xpath('//div/script/text()').extract_first()
u"\n        var i = {a:['O&#39;Connor Park']}\n    "
>>> 

现在,使用.re(或.re_first)可以得到不同的结果:

>>> # I'm using a very simple "catch-all" regex
>>> # you are probably using a regex to extract
>>> # that specific "O'Connor Park" string
>>> selector.xpath('//div/script/text()').re_first('.+')
u"        var i = {a:['O'Connor Park']}"
>>> 
>>> # .re() on the element itself, one needs to handle newlines
>>> selector.xpath('//div/script').re_first('.+')
u'<script type="text/javascript">'    # only first line extracted
>>> import re
>>> selector.xpath('//div/script').re_first(re.compile('.+', re.DOTALL))
u'<script type="text/javascript">\n        var i = {a:[\'O\'Connor Park\']}\n    </script>'
>>> 

HTML实体&#39;已被apostrophe替换。这是由于.re/re_first实现中的^{}调用(请参阅parsel源代码,在^{}函数中)导致的,在简单调用extract()extract_first()时不使用该调用

您还可以使用Selectorextract方法使用的相同函数,但参数不同:

from lxml import etree
etree.tostring(selector._root)

由于parsel 1.2.0(2017-05-17),您可以将replace_entities=False传递给rere_first以避免默认行为。

相关问题 更多 >