我是Python的新手,我正尝试使用BeautifulSoup从脚本中定义的变量中提取一些数据。
data = soup.find_all('script', type='text/javascript')
print(data[0])
<script type="text/javascript">
var myvar = {
productid: "101",
productname: "Abc",
};
</script>
您知道从myvar变量中提取“ productid”和“ productname”的简单方法吗?
答案 0 :(得分:1)
有两种方法。简单,错误。还是不太容易,但是正确。
我不会向您推荐简单的方法。正确的方法是使用Javascript解析器。对于现代Javascript,esprima是一个不错的选择。有一个interactive online demo,它也可以作为Python module使用。
... datetime
01:00:00
03:00:00
在这个简单的脚本中,没有太多事情发生。原始令牌列表足以获取所需的值。看起来像这样:
import esprima
# script body as extracted from beautifulsoup
script_text = """
var myvar = {
productid: "101",
productname: "Abc",
};
""";
tokens = esprima.tokenize(script_text)
遍历列表并选择所需的值。
[
{
"type": "Keyword",
"value": "var"
},
{
"type": "Identifier",
"value": "myvar"
},
{
"type": "Punctuator",
"value": "="
},
{
"type": "Punctuator",
"value": "{"
},
{
"type": "Identifier",
"value": "productid"
},
{
"type": "Punctuator",
"value": ":"
},
{
"type": "String",
"value": "\"101\""
},
{
"type": "Punctuator",
"value": ","
},
{
"type": "Identifier",
"value": "productname"
},
{
"type": "Punctuator",
"value": ":"
},
{
"type": "String",
"value": "\"Abc\""
},
{
"type": "Punctuator",
"value": ","
},
{
"type": "Punctuator",
"value": "}"
},
{
"type": "Punctuator",
"value": ";"
}
]
对于更复杂的情况,可能有必要将脚本解析成一棵树并沿着树走动。
token_iterator = iter(tokens)
for token in token_iterator:
if token["type"] == "Identifier" and token["value"] == "productname":
# the token after the next must be the one that holds the associated value
value_token = next(next(token_iterator))
productname = value_token["value"]
这棵树比较复杂(您可以在交互式页面上查看),但作为交换,它会携带普通令牌列表中缺少的所有上下文信息。然后,您将使用访问者模式将这棵树移至特定位置。如果您有兴趣,Python软件包中有一个example how to use the visitor pattern。
答案 1 :(得分:0)
解析
from bs4 import BeautifulSoup
script_data='''
<script type="text/javascript">
var myvar = {
productid: "101",
productname: "Abc",
};
</script>
'''
soup = BeautifulSoup(script_data)
soup.script.string
将script
标记内的数据保存为字符串。您可以在字符串上使用split
来获取位置数据:
soup.script.string.split()
Output:
['var',
'myvar',
'=',
'{',
'productid:',
'"101",',
'productname:',
'"Abc",',
'};']
product_id:
soup.script.string.split()[5].split('"')[1]
Output:
'101'
产品名称:
soup.script.string.split()[7].split('"')[1]
Output:
'Abc'
答案 2 :(得分:0)
为简单起见,我将使用正则表达式
import re
.....
data = soup.find_all('script', type='text/javascript')
productid = re.search(r'productid:\s*"(.*?)"', data[0].text).group(1)
print(productid)