选择器中提取原始

选择器中提取原始

本文介绍了如何从 Scrapy 选择器中提取原始 html?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 response.xpath('//*')re_first() 提取 js 数据,然后将其转换为 Python 本机数据.问题是提取/重新方法似乎没有提供一种不取消引用 html 的方法,即

原始 html:

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

提取输出:

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

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

最简单的方法是什么?

解决方案

简短回答:

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

长答案:

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

示例 HTML:

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

</html>

使用scrapy Selector,它在下面使用parsel 库,您可以通过多种方式提取Javascript 代码段:

>>>导入scrapy>>>t = """... <身体>... <div>... <script type="text/javascript">... var i = {a:['O&#39;Connor Park']}... </script>...... </div>... </body>... </html>……">>>selector = scrapy.Selector(text=t, type="html")>>>>>># 提取<脚本>元素作为原始 HTML>>>selector.xpath('//div/script').extract_first()u'<script type="text/javascript">\n var i = {a:[\'O&#39;Connor Park\']}\n </script>'>>>>>># 只获取 内的文本节点;元素>>>selector.xpath('//div/script/text()').extract_first()u"\n var i = {a:['O&#39;Connor Park']}\n ">>>

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

>>># 我正在使用一个非常简单的包罗万象"的正则表达式>>># 您可能正在使用正则表达式来提取>>># 那个特定的O'Connor Park"字符串>>>selector.xpath('//div/script/text()').re_first('.+')u" var i = {a:['O'Connor Park']}">>>>>># .re() 在元素本身上,需要处理换行符>>>selector.xpath('//div/script').re_first('.+')u'<script type="text/javascript">'# 只提取第一行>>>进口重新>>>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; 已替换为 撇号.这是由于 w3lib.html.replace_entities() 调用 .re/re_first 实现(参见 parsel 源代码,在 extract_regex 函数),仅在调用 extract()extract_first() 时不使用

I'm extracting js data using response.xpath('//*')re_first() and later converting it to python native data. The problem is extract/re methods don't seem to provide a way to not unquote html i.e.

original html:

{my_fields:['O&#39;Connor Park'], }

extract output:

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

turning this output into json won't work.

What's the easiest way around it?

解决方案

Short answer:

  • Scrapy/Parsel selectors' .re() and .re_first() methods replace HTML entities (except &lt;, &amp;)
  • instead, use .extract() or .extract_first() to get raw HTML (or raw JavaScript instructions) and use Python's re module on extracted string

Long answer:

Let's look at an example input and various ways of extracting Javascript data from HTML.

Sample HTML:

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

Using scrapy Selector, which is using the parsel library underneath, you have several ways of extracting the Javascript snippet:

>>> 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    "
>>>

Now, Using .re (or .re_first) you get different result:

>>> # 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>'
>>>

The HTML entity &#39; has been replaced by an apostrophe. This is due to a w3lib.html.replace_entities() call in .re/re_first implementation (see parsel source code, in extract_regex function), which is not used when simply calling extract() or extract_first()

这篇关于如何从 Scrapy 选择器中提取原始 html?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 21:26