在Python中使用BeautifulSoup提取script标签中的文本

6 投票
2 回答
23202 浏览
提问于 2025-04-18 15:52

我想从下面的代码中提取电子邮件、电话和姓名的值,这些代码是在SCRIPT标签里(而不是在页面主体中),我打算使用Beautiful Soup(Python库)来完成这个任务。我发现Beautiful Soup可以用来提取这些信息。

我尝试用以下代码获取页面 -

fileDetails = BeautifulSoup(urllib2.urlopen('http://www.example.com').read())
results = fileDetails.find(email:")

这个Ajax请求的代码在页面中没有重复出现。我们能不能写一个try和catch的结构,这样如果在页面中找不到它,就不会抛出错误。

<script type="text/javascript" language='javascript'> 
$(document).ready( function (){
   
   $('#message').click(function(){
       alert();
   });

    $('#addmessage').click(function(){
        $.ajax({ 
            type: "POST",
            url: 'http://www.example.com',
            data: { 
                email: 'abc@g.com', 
                phone: '9999999999', 
                name: 'XYZ'
            }
        });
    });
});

一旦我获取到这些信息,我还想把它们存储到一个Excel文件里。

谢谢你的帮助。

2 个回答

2

你可以通过 BeautifulSoup 来获取 script 标签里的内容,然后用正则表达式来提取你想要的数据。

这是一个工作示例(根据你在问题中描述的内容):

import re
from bs4 import BeautifulSoup

data = """
<html>
    <head>
        <title>My Sample Page</title>
        <script>
        $.ajax({
            type: "POST",
            url: 'http://www.example.com',
            data: {
                email: 'abc@g.com',
                phone: '9999999999',
                name: 'XYZ'
            }
        });
        </script>
    </head>
    <body>
        <h1>What a wonderful world</h1>
    </body>
</html>
"""

soup = BeautifulSoup(data)
script = soup.find('script')

pattern = re.compile("(\w+): '(.*?)'")
fields = dict(re.findall(pattern, script.text))
print fields['email'], fields['phone'], fields['name']

输出结果:

abc@g.com 9999999999 XYZ

我其实不太喜欢这个解决方案,因为用正则表达式的方法很脆弱。很多情况都可能导致它失效。我觉得还有更好的解决办法,我们可能忽略了更重要的事情。如果能提供那个特定网站的链接会帮助很多,但现在就是这样。


更新(修正了提问者提供的代码):

soup = BeautifulSoup(data, 'html.parser')
script = soup.html.find_next_sibling('script', text=re.compile(r"\$\(document\)\.ready"))

pattern = re.compile("(\w+): '(.*?)'")
fields = dict(re.findall(pattern, script.text))
print fields['email'], fields['phone'], fields['name']

输出结果:

abcd@gmail.com 9999999999 Shamita Shetty
8

除了使用正则表达式的方法,你还可以用slimit这个模块来解析JavaScript代码。这个模块会构建一个抽象语法树,让你可以提取所有的赋值操作,并把它们放进一个字典里。

from bs4 import BeautifulSoup
from slimit import ast
from slimit.parser import Parser
from slimit.visitors import nodevisitor


data = """
<html>
    <head>
        <title>My Sample Page</title>
        <script>
        $.ajax({
            type: "POST",
            url: 'http://www.example.com',
            data: {
                email: 'abc@g.com',
                phone: '9999999999',
                name: 'XYZ'
            }
        });
        </script>
    </head>
    <body>
        <h1>What a wonderful world</h1>
    </body>
</html>
"""

# get the script tag contents from the html
soup = BeautifulSoup(data)
script = soup.find('script')

# parse js
parser = Parser()
tree = parser.parse(script.text)
fields = {getattr(node.left, 'value', ''): getattr(node.right, 'value', '')
          for node in nodevisitor.visit(tree)
          if isinstance(node, ast.Assign)}

print fields

输出结果是:

{u'name': u"'XYZ'", u'url': u"'http://www.example.com'", u'type': u'"POST"', u'phone': u"'9999999999'", u'data': '', u'email': u"'abc@g.com'"}

在这些字段中,有emailnamephone是你比较关心的。

希望这对你有帮助。

撰写回答