使用Scrapy在JSON中刮取HTML

时间:2016-06-13 14:12:53

标签: scrapy scrapy-spider

我正在请求一个网站,其响应是这样的JSON:

{
    "success": true,
    "response": "<html>... html goes here ...</html>"
}

我已经看到了废弃HTML或JSON的两种方法,但还没有找到如何在JSON中废弃HTML。是否可以使用scrapy来做到这一点?

3 个答案:

答案 0 :(得分:7)

一种方法是在JSON数据中的HTML中构建scrapy.Selector

我假设你的Response对象包含JSON数据,可通过response.text获得。

(下面,我正在构建一个测试响应(我在Python 3中使用scrapy 1.1):

response = scrapy.http.TextResponse(url='http://www.example.com/json', body=r'''
{
    "success": true,
    "response": "<html>\n <head>\n  <base href='http://example.com/' />\n  <title>Example website</title>\n </head>\n <body>\n  <div id='images'>\n   <a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>\n   <a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>\n   <a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a>\n   <a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a>\n   <a href='image5.html'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a>\n  </div>\n </body>\n</html>"
}
''', encoding='utf8')

使用json模块,您可以获得如下的HTML数据:

import json
data = json.loads(response.text)

你会得到类似的东西:

>>> data
{'success': True, 'response': "<html>\n <head>\n  <base href='http://example.com/' />\n  <title>Example website</title>\n </head>\n <body>\n  <div id='images'>\n   <a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>\n   <a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>\n   <a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a>\n   <a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a>\n   <a href='image5.html'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a>\n  </div>\n </body>\n</html>"}

然后你可以建立一个像这样的新选择器:

selector = scrapy.Selector(text=data['response'], type="html")

之后你可以在其上使用XPath或CSS选择器:

>>> selector.xpath('//title/text()').extract()
['Example website']

答案 1 :(得分:0)

你可以尝试json.loads(initial_response),这样你就可以使用他的密钥,比如['response']

答案 2 :(得分:0)

好吧,还有另外一种方法,你绝对不需要构建一个响应对象。你可以使用lxml来解析你的html文本。您不需要安装任何新的lib,因为Scrapy Selector基于lxml。只需将以下代码添加到 import lxml lib。

from lxml import etree

这是一个例子,假设json响应为:

{
    "success": true,
    "htmlinjson": "<html><body> <p id='p1'>p111111</p> <p id='p2'>p22222</p> </html>"
}

通过以下方式从json响应中提取html文本:

import json

htmlText = json.loads(response.text)['htmlinjson']

然后使用:

构造一个lxml xpath selcector
from lxml import etree

resultPage = etree.HTML(htmlText)

现在使用lxml选择器以id =“p1”提取节点

的文本,基于xpath,就像scrapy xpath选择器一样:

print resultPage.xpath('//p[@id="p1"]')[0].text

你会得到:

  

p111111

希望有所帮助:)