- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试从 HTML 脚本中提取(看起来是)JSON 数据。 HTML 脚本在网站上如下所示:
<script>
$(document).ready(function(){
var terms = new Verba.Compare.Collections.Terms([{"id":"6436","name":"SUMMER 16","inquiry":true,"ordering":true},{"id":"6517","name":"FALL 16","inquiry":true,"ordering":true}]);
var view = new Verba.Compare.Views.CourseSelector({el: "body", terms: terms});
});
</script>
我想提取以下内容:
[{"id":"6436","name":"SUMMER 16","inquiry":true,"ordering":true},{"id":"6517","name":"FALL 16","inquiry":true,"ordering":true}]
使用以下代码,我可以获得完整的脚本。
def parse(self, response):
print response.xpath('/html/body/script[2]').extract()
有没有一种简单的方法可以从该脚本中提取“id”、“name”等的值。或者有没有更直接的方法,修改xpath?我似乎无法使用 firebug 更深入地了解 xpath。
最佳答案
您可以使用js2xml为此。
为了说明这一点,首先,让我们使用示例 HTML 创建一个 Scrapy 选择器,并获取 JavaScript 语句:
>>> import scrapy
>>> sample = '''<script>
... $(document).ready(function(){
... var terms = new Verba.Compare.Collections.Terms([{"id":"6436","name":"SUMMER 16","inquiry":true,"ordering":true},{"id":"6517","name":"FALL 16","inquiry":true,"ordering":true}]);
... var view = new Verba.Compare.Views.CourseSelector({el: "body", terms: terms});
... });
... </script>'''
>>> selector = scrapy.Selector(text=sample, type='html')
>>> selector.xpath('//script//text()').extract_first()
u'\n $(document).ready(function(){\n var terms = new Verba.Compare.Collections.Terms([{"id":"6436","name":"SUMMER 16","inquiry":true,"ordering":true},{"id":"6517","name":"FALL 16","inquiry":true,"ordering":true}]);\n var view = new Verba.Compare.Views.CourseSelector({el: "body", terms: terms});\n });\n'
然后我们就可以用js2xml解析JavaScript代码了。你会得到一个 lxml 树:
>>> import js2xml
>>> jssnippet = selector.xpath('//script//text()').extract_first()
>>> jstree = js2xml.parse(jssnippet)
>>> jstree
<Element program at 0x7fc7c6bae1b8>
这棵树长什么样?这相当冗长:
>>> print(js2xml.pretty_print(jstree))
<program>
<functioncall>
<function>
<dotaccessor>
<object>
<functioncall>
<function>
<identifier name="$"/>
</function>
<arguments>
<identifier name="document"/>
</arguments>
</functioncall>
</object>
<property>
<identifier name="ready"/>
</property>
</dotaccessor>
</function>
<arguments>
<funcexpr>
<identifier/>
<parameters/>
<body>
<var name="terms">
<new>
<dotaccessor>
<object>
<dotaccessor>
<object>
<dotaccessor>
<object>
<identifier name="Verba"/>
</object>
<property>
<identifier name="Compare"/>
</property>
</dotaccessor>
</object>
<property>
<identifier name="Collections"/>
</property>
</dotaccessor>
</object>
<property>
<identifier name="Terms"/>
</property>
</dotaccessor>
<arguments>
<array>
<object>
<property name="id">
<string>6436</string>
</property>
<property name="name">
<string>SUMMER 16</string>
</property>
<property name="inquiry">
<boolean>true</boolean>
</property>
<property name="ordering">
<boolean>true</boolean>
</property>
</object>
<object>
<property name="id">
<string>6517</string>
</property>
<property name="name">
<string>FALL 16</string>
</property>
<property name="inquiry">
<boolean>true</boolean>
</property>
<property name="ordering">
<boolean>true</boolean>
</property>
</object>
</array>
</arguments>
</new>
</var>
<var name="view">
<new>
<dotaccessor>
<object>
<dotaccessor>
<object>
<dotaccessor>
<object>
<identifier name="Verba"/>
</object>
<property>
<identifier name="Compare"/>
</property>
</dotaccessor>
</object>
<property>
<identifier name="Views"/>
</property>
</dotaccessor>
</object>
<property>
<identifier name="CourseSelector"/>
</property>
</dotaccessor>
<arguments>
<object>
<property name="el">
<string>body</string>
</property>
<property name="terms">
<identifier name="terms"/>
</property>
</object>
</arguments>
</new>
</var>
</body>
</funcexpr>
</arguments>
</functioncall>
</program>
您可以使用 XPath 技能指向 JavaScript 数组(您希望将 new
结构的“点”访问器的第一个参数分配给 var terms
):
>>> jstree.xpath('//var[@name="terms"]')
[<Element var at 0x7fc7c565e638>]
>>> jstree.xpath('//var[@name="terms"]/new/arguments/*')
[<Element array at 0x7fc7c565e5a8>]
>>> jstree.xpath('//var[@name="terms"]/new/arguments/*')[0]
<Element array at 0x7fc7c565e5a8>
最后,现在您已经有了 <array>
元素,您可以将其传递给 js2xml.jsonlike.make_dict()
获得一个不错的 Python 对象来使用( make_dict
有点错误命名):
>>> js2xml.jsonlike.make_dict(jstree.xpath('//var[@name="terms"]/new/arguments/*')[0])
[{'ordering': True, 'inquiry': True, 'id': '6436', 'name': 'SUMMER 16'}, {'ordering': True, 'inquiry': True, 'id': '6517', 'name': 'FALL 16'}]
>>>
注意:您还可以使用快捷方式 js2xml.jsonlike.getall()
获取所有看起来像 Python 字典或列表的内容(你得到 2 个列表,你对第一个列表感兴趣):
>>> js2xml.jsonlike.getall(jstree)
[[{'ordering': True, 'inquiry': True, 'id': '6436', 'name': 'SUMMER 16'}, {'ordering': True, 'inquiry': True, 'id': '6517', 'name': 'FALL 16'}], {'el': 'body', 'terms': 'terms'}]
关于python - Scrapy:从 HTML 脚本中提取 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38470261/
最近开始学习MongoDB。今天老师教了我们 mongoexport 命令。在练习时,我遇到了一个典型的问题,包括教练在内的其他同学都没有遇到过。我在我的 Windows 10 机器上使用 Mongo
我是 JSON Schema 的新手,读过什么是 JSON Schema 等等。但我不知道如何将 JSON Schema 链接到 JSON 以针对该 JSON Schema 进行验证。谁能解释一下?
在 xml 中,我可以在另一个 xml 文件中包含一个文件并使用它。如果您的软件从 xml 获取配置文件但没有任何方法来分离配置,如 apache/ngnix(nginx.conf - site-av
我有一个 JSON 对象,其中包含一个本身是 JSON 对象的字符串。我如何反序列化它? 我希望能够做类似的事情: #[derive(Deserialize)] struct B { c: S
考虑以下 JSON { "a": "{\"b\": 12, \"c\": \"test\"}" } 我想定义一个泛型读取 Reads[Outer[T]]对于这种序列化的 Json import
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 11 个月前关闭。 Improve
我的旧项目在 MySQL 中有 Standard JSON 格式的数据。 对于我在 JS (Node.js) 和 DynamoDB 中的全新项目,关于 Standard JSON格式: 是否建议将其转
JSON 值字符串、数字、true、false、null 是否是有效的 JSON? 即,是 true 一个有效的 JSON 文档?还是必须是数组/对象? 一些验证器接受这个(例如 http://jso
我有一个 JSON 字符串,其中一个字段是文本字段。这个文本字段可以包含用户在 UI 中输入的文本,如果他们输入的文本是 JSON 文本,也许是为了说明一些编码,我需要对他们的文本进行编码,以便它不会
我正在通过 IBM MQ 调用处理数据,当由 ColdFusion 10 (10,0,11,285437) 序列化时,0 将作为 +0.0 返回,它会导致无效的 JSON并且无法反序列化。 stPol
我正在从三个数组中生成一个散列,然后尝试构建一个 json。我通过 json object has array 成功了。 require 'json' A = [['A1', 'A2', 'A3'],
我从 API 接收 JSON,响应可以是 30 种类型之一。每种类型都有一组唯一的字段,但所有响应都有一个字段 type 说明它是哪种类型。 我的方法是使用serde .我为每种响应类型创建一个结构并
我正在下载一个 JSON 文件,我已将其检查为带有“https://jsonlint.com”的有效 JSON 到文档目录。然后我打开文件并再次检查,结果显示为无效的 JSON。这怎么可能????这是
我正在尝试根据从 API 接收到的数据动态创建一个 JSON 对象。 收到的示例数据:将数据解码到下面给出的 CiItems 结构中 { "class_name": "test", "
我想从字符串转换为对象。 来自 {"key1": "{\n \"key2\": \"value2\",\n \"key3\": {\n \"key4\": \"value4\"\n }\n
目前我正在使用以下代码将嵌套的 json 转换为扁平化的 json: import ( "fmt" "github.com/nytlabs/gojsonexplode" ) func
我有一个使用来自第三方 API 的数据的应用程序。我需要将 json 解码为一个结构,这需要该结构具有“传入”json 字段的 json 标签。传出的 json 字段具有不同的命名约定,因此我需要不同
我想使用 JSON 架构来验证某些值。我有两个对象,称它们为 trackedItems 和 trackedItemGroups。 trackedItemGroups 是组名称和 trackedItem
考虑以下案例类模式, case class Y (a: String, b: String) case class X (dummy: String, b: Y) 字段b是可选的,我的一些数据集没有字
我正在存储 cat ~/path/to/file/blah | 的输出jq tojson 在一个变量中,稍后在带有 JSON 内容的 curl POST 中使用。它运作良好,但它删除了所有换行符。我知
我是一名优秀的程序员,十分优秀!