我需要在下面的JavaScript源代码中获取“html”键的值,该源代码由xpath('。// script [34]')提取并嵌入到html源页面中。
<script>
FM.view({
"ns": "pl.content.homeFeed.index",
"domid": "Pl_Official_MyProfileFeed__24",
"css": ["style/css/module/list/comb_WB_feed_profile.css?version=73267f08bd52356e"],
"js": "page/js/pl/content/homeFeed/index.js?version=dad90e594db2c334",
"html": " <div class=\"WB_feed WB_feed_v3\" pageNum=\"\" node-type='feed_list' module-type=\"feed\">\r\n...."
})
</script>
我不知道如何处理文本“FM.view”。
答案 0 :(得分:2)
我会使用.re()
从脚本中提取html
键值:
>>> response.xpath("//script[contains(., 'Pl_Official_MyProfileFeed__24')]/text()").re(r'"html": "(.*?)"\n')
[0].strip()
u'<div class=\\"WB_feed WB_feed_v3\\" pageNum=\\"\\" node-type=\'feed_list\' module-type=\\"feed\\">\\r\\n..'
或者,您可以从脚本中提取完整对象,使用json
加载它并获取html
值:
>>> import json
>>> data = response.xpath("//script[contains(., 'Pl_Official_MyProfileFeed__24')]/text()").re(r'(?ms)FM\.view\((\{.*?\})\)')[0]
>>> obj = json.loads(data)
>>> obj['html'].strip()
u'<div class="WB_feed WB_feed_v3" pageNum="" node-type=\'feed_list\' module-type="feed">\r\n....'
注意正则表达式中的(?ms)
部分 - 这是我们设置标志的方式 - 多行和dotall - 在这种情况下模式可以工作。
答案 1 :(得分:2)
这是使用js2xml
包的正则表达式+ json的替代方法。
第一步是从HTML中获取<script>
中的JavaScript语句。你可能已经迈出了这一步。在这里,我正在从您的输入HTML构建一个Scrapy选择器。在您的情况下,您可能正在使用回调中的response
:
>>> import scrapy
>>> import js2xml
>>> t = r''' <script>
... FM.view({
... "ns": "pl.content.homeFeed.index",
... "domid": "Pl_Official_MyProfileFeed__24",
... "css": ["style/css/module/list/comb_WB_feed_profile.css?version=73267f08bd52356e"],
... "js": "page/js/pl/content/homeFeed/index.js?version=dad90e594db2c334",
... "html": " <div class=\"WB_feed WB_feed_v3\" pageNum=\"\" node-type='feed_list' module-type=\"feed\">\r\n...."
... })
... </script>'''
>>> selector = scrapy.Selector(text=t, type='html')
第二步是使用js2xml.parse()
构建JavaScript程序的树表示。你得到一个lxml树:
>>> js = selector.xpath('//script/text()').extract_first()
>>> jstree = js2xml.parse(js)
>>> jstree
<Element program at 0x7ff19ec94ea8>
>>> type(jstree)
<type 'lxml.etree._Element'>
>>> print(js2xml.pretty_print(jstree))
<program>
<functioncall>
<function>
<dotaccessor>
<object>
<identifier name="FM"/>
</object>
<property>
<identifier name="view"/>
</property>
</dotaccessor>
</function>
<arguments>
<object>
<property name="ns">
<string>pl.content.homeFeed.index</string>
</property>
<property name="domid">
<string>Pl_Official_MyProfileFeed__24</string>
</property>
<property name="css">
<array>
<string>style/css/module/list/comb_WB_feed_profile.css?version=73267f08bd52356e</string>
</array>
</property>
<property name="js">
<string>page/js/pl/content/homeFeed/index.js?version=dad90e594db2c334</string>
</property>
<property name="html">
<string> <div class="WB_feed WB_feed_v3" pageNum="" node-type='feed_list' module-type="feed">
....</string>
</property>
</object>
</arguments>
</functioncall>
</program>
第三是从树中选择所需的对象。
在这里,它是FM.view()
调用的第一个参数。即使您选择了1个节点(XPath返回节点集),在lxml树上调用.xpath()
也会为您提供一个列表
# select the function call for "FM.view"
# and get first argument
>>> jstree.xpath('''
//functioncall[
function[.//identifier/@name="FM"]
[.//identifier/@name="view"]]
/arguments
/*[1]''')
[<Element object at 0x7ff19ec94ef0>]
>>> args = jstree.xpath('//functioncall[function[.//identifier/@name="FM"][.//identifier/@name="view"]]/arguments/*[1]')
第四,使用<object>
将js2xml.jsonlike.make_dict()
转换为Python dict:
# use js2xml.jsonlike.make_dict() on that argument
>>> js2xml.jsonlike.make_dict(args[0])
{'ns': 'pl.content.homeFeed.index', 'html': ' <div class="WB_feed WB_feed_v3" pageNum="" node-type=\'feed_list\' module-type="feed">\r\n....', 'css': ['style/css/module/list/comb_WB_feed_profile.css?version=73267f08bd52356e'], 'domid': 'Pl_Official_MyProfileFeed__24', 'js': 'page/js/pl/content/homeFeed/index.js?version=dad90e594db2c334'}
>>> from pprint import pprint
>>> pprint(js2xml.jsonlike.make_dict(args[0]))
{'css': ['style/css/module/list/comb_WB_feed_profile.css?version=73267f08bd52356e'],
'domid': 'Pl_Official_MyProfileFeed__24',
'html': ' <div class="WB_feed WB_feed_v3" pageNum="" node-type=\'feed_list\' module-type="feed">\r\n....',
'js': 'page/js/pl/content/homeFeed/index.js?version=dad90e594db2c334',
'ns': 'pl.content.homeFeed.index'}
>>>
最后,您只需使用该词典中的“html”键:
>>> jsdata = js2xml.jsonlike.make_dict(args[0])
>>> jsdata['html']
' <div class="WB_feed WB_feed_v3" pageNum="" node-type=\'feed_list\' module-type="feed">\r\n....'
>>>