<p>您可以使用<a href="https://github.com/scrapinghub/js2xml" rel="nofollow">js2xml</a>进行此操作。在</p>
<p>为了说明这一点,首先,让我们用示例HTML创建一个糟糕的选择器,并获取JavaScript语句:</p>
<pre><code>>>> 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'
</code></pre>
<p>然后我们可以用js2xml解析JavaScript代码。你得到了一棵lxml树:</p>
^{pr2}$
<p>这棵树长什么样?很冗长:</p>
<pre><code>>>> 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>
</code></pre>
<p>您可以使用XPath技巧来指向JavaScript数组(您希望将<code>new</code>构造的“dot”访问器的第一个参数分配给<code>var terms</code>):</p>
<pre><code>>>> 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>
</code></pre>
<p>最后,既然有了<code><array></code>元素,就可以将其传递给<code>js2xml.jsonlike.make_dict()</code>以获得一个好的Python对象来使用(<code>make_dict</code>有点误名):</p>
<pre><code>>>> 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'}]
>>>
</code></pre>
<p>注意:您还可以使用快捷键<code>js2xml.jsonlike.getall()</code>来获取所有看起来像Python dict或list的内容(如果有2个列表,您对第一个列表感兴趣):</p>
<pre><code>>>> 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'}]
</code></pre>