2016-01-19 58 views
3

我使用response.xpath('// *')re_first()提取js數據,稍後將其轉換爲python原生數據。問題是提取/重方法似乎並沒有提供一種方式來不是所享有的HTML,即如何從Scrapy選擇器中提取原始html?

原始的HTML:

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

提取輸出:

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

把這個輸出爲JSON韓元沒有工作。

最簡單的方法是什麼?

回答

6

簡短的回答:

  • 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實施w3lib.html.replace_entities()調用(見parsel源代碼,extract_regex功能),這是不使用時簡單地調用extract()extract_first()

+0

優秀的答案! Scrapy的文檔使這些相關方法的不一致性更加混亂。它不僅沒有提到html實體,而且還提到「百分比編碼的內容沒有被引用」。僅通過extract()。這意味着如果有任何提取是比re()更多的解碼。 – jayshilling

0

您還可以利用所使用的Selector類的相同功能extract方法,但有不同的參數:

from lxml import etree 
etree.tostring(selector._root) 
相關問題