因此,我一直在尝试从javascript的html中抓取一个值。代码中有很多javascript,但是我只想能够打印出这一个:
var spConfig=newProduct.Config({
"attributes": {
"531": {
"id": "531",
"options": [
{
"id": "18",
"hunter": "0",
"products": [
"128709"
]
},
{
"label": "40 1\/2",
"hunter": "0",
"products": [
"120151"
]
},
{
"id": "33",
"hunter": "0",
"products": [
"120152"
]
},
{
"id": "36",
"hunter": "0",
"products": [
"128710"
]
},
{
"id": "42",
"hunter": "0",
"products": [
"125490"
]
}
]
}
},
"Id": "120153",
});
因此,我首先编写了如下代码:
test = bs4.find_all('script', {'type': 'text/javascript'})
print(test)
我得到的输出非常巨大,因此我无法将其全部发布到此处,但是其中之一就是我在顶部提到的javascript,我只想打印出var spConfig=newProduct.Config
。
如何做到这一点,以便能够打印出var spConfig=newProduct.Config....
,以后我可以使用json.loads将其转换为json,以后我可以更轻松地对其进行抓取了?
对于任何问题或我没有很好解释的问题。我会在注释中说明所有内容,在这里我可以在stackoverflow中提高自己! :)
编辑:
bs4为javascript打印出的更多示例
<script type="text/javascript">varoptionsPrice=newProduct.Options({
"priceFormat": {
"pattern": "%s\u00a0\u20ac",
"precision": 2,
"requiredPrecision": 2,
"decimalSymbol": ",",
"groupSymbol": "\u00a0",
"groupLength": 3,
"integerRequired": 1
},
"showBoths": false,
"idSuffix": "_clone",
"skipCalculate": 1,
"defaultTax": 20,
"currentTax": 20,
"tierPrices": [
],
"tierPricesInclTax": [
],
"swatchPrices": null
});</script>,
<script type="text/javascript">var spConfig=newProduct.Config({
"attributes": {
"531": {
"id": "531",
"options": [
{
"id": "18",
"hunter": "0",
"products": [
"128709"
]
},
{
"label": "40 1\/2",
"hunter": "0",
"products": [
"120151"
]
},
{
"id": "33",
"hunter": "0",
"products": [
"120152"
]
},
{
"id": "36",
"hunter": "0",
"products": [
"128710"
]
},
{
"id": "42",
"hunter": "0",
"products": [
"125490"
]
}
]
}
},
"Id": "120153"
});</script>,
<scripttype="text/javascript">document.observe('dom:loaded',
function(){
varswatchesConfig=newProduct.ConfigurableSwatches(spConfig);
});</script>
编辑更新2:
try:
product_li_tags = bs4.find_all('script', {'type': 'text/javascript'})
except Exception:
product_li_tags = []
for product_li_tag in product_li_tags:
try:
pat = "product.Config\((.+)\);"
json_str = re.search(pat, product_li_tag, flags=re.DOTALL).group(1)
print(json_str)
except:
pass
#json.loads(json_str)
print("Nothing")
sys.exit()
答案 0 :(得分:1)
我可以想到3个选项-您使用哪个选项可能取决于项目的规模以及所需的灵活性
使用Regex从脚本中提取对象(最快,最不灵活)
使用ANTLR或类似的语言(例如pyjsparser)来解析js语法
使用Selenium或其他无头浏览器可以为您解释JS。使用此选项,您可以使用selenium执行调用以获取变量like this
>>> script_body = """
var x=product.Config({
"key": {"a":1}
});
"""
>>> pat = "product.Config\((.+)\);"
>>> json_str = re.search(pat, script_body, flags=re.DOTALL).group(1)
>>> json.loads(json_str)
{'key': {'a': 1}}
>>> json.loads(json_str)['key']['a']
1
答案 1 :(得分:1)
您可以使用.text
函数来获取每个标签中的内容。然后,如果您知道要获取以“ varoptionsPrice
”开头的代码,则可以对此进行过滤:
soup = BeautifulSoup(myhtml, 'lxml')
script_blocks = soup.find_all('script', {'type': 'text/javascript'})
special_code = ''
for s in script_blocks:
if s.text.strip().startswith('varOptionsPrice'):
special_code = s.text
break
print(special_code)
编辑:要在评论中回答您的问题,有两种不同的方法来提取文本中具有JSON的部分。您可以通过正则表达式传递它,以获取第一个左括号之间和末尾);
之间的所有内容。尽管如果您想完全避免使用正则表达式,则可以执行以下操作:
json_stuff = special_code[special_code.find('(')+1:special_code.rfind(')')]
然后从中制作出可用的字典:
import json
j = json.loads(json_stuff)
print(j['defaultTax']) # This should return a value of 20