首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从javascript (编码)变量中抓取BeautifulSoup

从javascript (编码)变量中抓取BeautifulSoup
EN

Stack Overflow用户
提问于 2014-08-07 05:43:58
回答 2查看 1.6K关注 0票数 2

我正在抓取一个页面,无法获取某个字段,因为它存储在一个javascript变量中。

我的问题是,如何抓取以下代码,对其进行解码,并保存<li>标记内容?使用BeautifulSoup和其他任何python。

下面是<script>标记中的代码:

代码语言:javascript
运行
复制
<script type="text/javascript">
    var html_audition_details_sidebar = '    \u003Cdiv id\u003D\u0022apply_wrapper\u0022\u003E        \u003Cdiv class\u003D\u0022header\u0022\u003E            \u003Cp\u003EAudition Information\u003C/p\u003E        \u003C/div\u003E        \u003Cdiv class\u003D\u0022text  \u0022\u003E            \u003Cdiv class\u003D\u0022roleContainer \u0022 style\u003D\u0022color: #999\u003B font\u002Dsize: 14px\u003B\u0022\u003E                \u003Cp\u003EOnly official members can see audition information for this job\u003C/p\u003E            \u003C/div\u003E        \u003C/div\u003E        \u003Cdiv class\u003D\u0022applyButton\u0022\u003E            \u003Cp\u003E\u003Ca class\u003D\u0022applyLink\u0022                                        href\u003D\u0022/accounts/login/apply/41680/\u0022\u003ESubscribe Now                  \u003C/a\u003E\u003C/p\u003E        \u003C/div\u003E    \u003C/div\u003E';
    var html_additional_requirements = '';
    var html_role_listing = '\u003Cdiv class\u003D\u0022text callListing loggedout \u0022\u003E    \u003Cp class\u003D\u0022title\u0022\u003E\u003Ca name\u003D\u0022roles\u0022\u003E\u003C/a\u003ESeeking Talent \u003Cspan class\u003D\u0022optional\u0022\u003ESelect a role below for more information and submission instructions.\u003C/span\u003E\u003C/p\u003E    \u003Cdiv class\u003D\u0022castingRoles\u0022\u003E        \u003Cul\u003E                                \u003Cli \u003E                \u003Ca href\u003D\u0022/casting/untitled\u002Dcomedy\u002Dshort\u002D41680/martinique\u002D159296/\u0022\u003E                    Martinique  (Lead):                \u003Cspan class\u003D\u0022roletag\u0022\u003E                    Female, 18\u002D25, Caucasian                \u003C/span\u003E                \u003Cspan class\u003D\u0022applyNow\u0022\u003E \u003C/span\u003E                \u003C/a\u003E                \u003Cp class\u003D\u0022role\u002Ddesc\u0022                   style\u003D\u0022border\u002Dbottom: none\u003B padding\u002Dbottom: 0px\u003B margin\u002Dbottom: 0px\u003B\u0022\u003E                    native French speaker.                \u003C/p\u003E            \u003C/li\u003E                                            \u003Cli \u003E                \u003Ca href\u003D\u0022/casting/untitled\u002Dcomedy\u002Dshort\u002D41680/justin\u002D159297/\u0022\u003E                    Justin  (Lead):                \u003Cspan class\u003D\u0022roletag\u0022\u003E                    Male, 20\u002D25, All Ethnicities                \u003C/span\u003E                \u003Cspan class\u003D\u0022applyNow\u0022\u003E \u003C/span\u003E                \u003C/a\u003E                \u003Cp class\u003D\u0022role\u002Ddesc\u0022                   style\u003D\u0022border\u002Dbottom: none\u003B padding\u002Dbottom: 0px\u003B margin\u002Dbottom: 0px\u003B\u0022\u003E                    comedy and improv skills, hopeless romantic.                \u003C/p\u003E            \u003C/li\u003E                                            \u003Cli \u003E                \u003Ca href\u003D\u0022/casting/untitled\u002Dcomedy\u002Dshort\u002D41680/flower\u002Dshop\u002Dsalesperson\u002D159299/\u0022\u003E                    Flower Shop Salesperson :                \u003Cspan class\u003D\u0022roletag\u0022\u003E                    Males \u0026amp\u003B Females, 30+, All Ethnicities                \u003C/span\u003E                \u003Cspan class\u003D\u0022applyNow\u0022\u003E \u003C/span\u003E                \u003C/a\u003E                \u003Cp class\u003D\u0022role\u002Ddesc\u0022                   style\u003D\u0022border\u002Dbottom: none\u003B padding\u002Dbottom: 0px\u003B margin\u002Dbottom: 0px\u003B\u0022\u003E                    impatient.                \u003C/p\u003E            \u003C/li\u003E                                            \u003Cli \u003E                \u003Ca href\u003D\u0022/casting/untitled\u002Dcomedy\u002Dshort\u002D41680/models\u002D159300/\u0022\u003E                    Models  (Supporting):                \u003Cspan class\u003D\u0022roletag\u0022\u003E                    Female, 18\u002D35, All Ethnicities                \u003C/span\u003E                \u003Cspan class\u003D\u0022applyNow\u0022\u003E \u003C/span\u003E                \u003C/a\u003E                \u003Cp class\u003D\u0022role\u002Ddesc\u0022                   style\u003D\u0022border\u002Dbottom: none\u003B padding\u002Dbottom: 0px\u003B margin\u002Dbottom: 0px\u003B\u0022\u003E                    small roles, under five lines.                \u003C/p\u003E            \u003C/li\u003E                            \u003C/ul\u003E    \u003C/div\u003E\u003C/div\u003E';
</script>

这是可怕的格式,我道歉。

我只需要为变量html_role_listing保存所有li标记内的urls。

示例:

旋转此选项:

代码语言:javascript
运行
复制
\u003Ca href\u003D\u0022/casting/untitled\u002Dcomedy\u002Dshort\u002D41680/martinique\u002D159296/\u0022\u003E

如下所示:

代码语言:javascript
运行
复制
/casting/untitled-comedy-short-41680/martinique-159296/

提前感谢您的帮助!

EN

回答 2

Stack Overflow用户

发布于 2014-11-16 10:54:15

如果你想以一种通用的方式来做这件事,你需要一个能解析javascript的库。在本例中,我将使用slimit来完成此操作。

首先,加载您的数据:

代码语言:javascript
运行
复制
from bs4 import BeautifulSoup as Soup
import slimit
from slimit.parser import Parser
from slimit.visitors import nodevisitor    

a = """<script type="text/javascript">
    var html_audition_details_sidebar = '    \u003Cdiv id\u003D\u0022apply_wrapper\u0022\u003E        \u003Cdiv class\u003D\u0022header\u0022\u003E            \u003Cp\u003EAudition Information\u003C/p\u003E        \u003C/div\u003E        \u003Cdiv class\u003D\u0022text  \u0022\u003E            \u003Cdiv class\u003D\u0022roleContainer \u0022 style\u003D\u0022color: #999\u003B font\u002Dsize: 14px\u003B\u0022\u003E                \u003Cp\u003EOnly official members can see audition information for this job\u003C/p\u003E            \u003C/div\u003E        \u003C/div\u003E        \u003Cdiv class\u003D\u0022applyButton\u0022\u003E            \u003Cp\u003E\u003Ca class\u003D\u0022applyLink\u0022                                        href\u003D\u0022/accounts/login/apply/41680/\u0022\u003ESubscribe Now                  \u003C/a\u003E\u003C/p\u003E        \u003C/div\u003E    \u003C/div\u003E';
    var html_additional_requirements = '';
    var html_role_listing = '\u003Cdiv class\u003D\u0022text callListing loggedout \u0022\u003E    \u003Cp class\u003D\u0022title\u0022\u003E\u003Ca name\u003D\u0022roles\u0022\u003E\u003C/a\u003ESeeking Talent \u003Cspan class\u003D\u0022optional\u0022\u003ESelect a role below for more information and submission instructions.\u003C/span\u003E\u003C/p\u003E    \u003Cdiv class\u003D\u0022castingRoles\u0022\u003E        \u003Cul\u003E                                \u003Cli \u003E                \u003Ca href\u003D\u0022/casting/untitled\u002Dcomedy\u002Dshort\u002D41680/martinique\u002D159296/\u0022\u003E                    Martinique  (Lead):                \u003Cspan class\u003D\u0022roletag\u0022\u003E                    Female, 18\u002D25, Caucasian                \u003C/span\u003E                \u003Cspan class\u003D\u0022applyNow\u0022\u003E \u003C/span\u003E                \u003C/a\u003E                \u003Cp class\u003D\u0022role\u002Ddesc\u0022                   style\u003D\u0022border\u002Dbottom: none\u003B padding\u002Dbottom: 0px\u003B margin\u002Dbottom: 0px\u003B\u0022\u003E                    native French speaker.                \u003C/p\u003E            \u003C/li\u003E                                            \u003Cli \u003E                \u003Ca href\u003D\u0022/casting/untitled\u002Dcomedy\u002Dshort\u002D41680/justin\u002D159297/\u0022\u003E                    Justin  (Lead):                \u003Cspan class\u003D\u0022roletag\u0022\u003E                    Male, 20\u002D25, All Ethnicities                \u003C/span\u003E                \u003Cspan class\u003D\u0022applyNow\u0022\u003E \u003C/span\u003E                \u003C/a\u003E                \u003Cp class\u003D\u0022role\u002Ddesc\u0022                   style\u003D\u0022border\u002Dbottom: none\u003B padding\u002Dbottom: 0px\u003B margin\u002Dbottom: 0px\u003B\u0022\u003E                    comedy and improv skills, hopeless romantic.                \u003C/p\u003E            \u003C/li\u003E                                            \u003Cli \u003E                \u003Ca href\u003D\u0022/casting/untitled\u002Dcomedy\u002Dshort\u002D41680/flower\u002Dshop\u002Dsalesperson\u002D159299/\u0022\u003E                    Flower Shop Salesperson :                \u003Cspan class\u003D\u0022roletag\u0022\u003E                    Males \u0026amp\u003B Females, 30+, All Ethnicities                \u003C/span\u003E                \u003Cspan class\u003D\u0022applyNow\u0022\u003E \u003C/span\u003E                \u003C/a\u003E                \u003Cp class\u003D\u0022role\u002Ddesc\u0022                   style\u003D\u0022border\u002Dbottom: none\u003B padding\u002Dbottom: 0px\u003B margin\u002Dbottom: 0px\u003B\u0022\u003E                    impatient.                \u003C/p\u003E            \u003C/li\u003E                                            \u003Cli \u003E                \u003Ca href\u003D\u0022/casting/untitled\u002Dcomedy\u002Dshort\u002D41680/models\u002D159300/\u0022\u003E                    Models  (Supporting):                \u003Cspan class\u003D\u0022roletag\u0022\u003E                    Female, 18\u002D35, All Ethnicities                \u003C/span\u003E                \u003Cspan class\u003D\u0022applyNow\u0022\u003E \u003C/span\u003E                \u003C/a\u003E                \u003Cp class\u003D\u0022role\u002Ddesc\u0022                   style\u003D\u0022border\u002Dbottom: none\u003B padding\u002Dbottom: 0px\u003B margin\u002Dbottom: 0px\u003B\u0022\u003E                    small roles, under five lines.                \u003C/p\u003E            \u003C/li\u003E                            \u003C/ul\u003E    \u003C/div\u003E\u003C/div\u003E';
</script>"""
soup = Soup(a)
js_content = soup.findAll('script')[0].text

现在您可以选择:使用正则表达式解析js_content或使用词法分析器(本例中为slimit)。

代码语言:javascript
运行
复制
par = Parser()
tree = par.parse(js_content)
encoded_html = [n.value for n in nodevisitor.visit(tree) if isinstance(n, slimit.ast.String)][2]

最后,您可以轻松地解码该字符串,它是有效的HTML:

代码语言:javascript
运行
复制
decoded_html = encoded_html.decode('unicode_escape')
print(decoded_html)

所以重新解析这个HTML:

代码语言:javascript
运行
复制
role_listing = Soup(decoded_html)
output = [ anchor.attrs['href'] for anchor in role_listing.select('li a') ]
print('---')
print("\n".join(output))

输出如下所示:

代码语言:javascript
运行
复制
'<div class="text callListing loggedout ">    <p class="title"><a name="roles"></a>Seeking Talent <span class="optional">Select a role below for more information and submission instructions.</span></p>    <div class="castingRoles">        <ul>                                <li >                <a href="/casting/untitled-comedy-short-41680/martinique-159296/">                    Martinique  (Lead):                <span class="roletag">                    Female, 18-25, Caucasian                </span>                <span class="applyNow"> </span>                </a>                <p class="role-desc"                   style="border-bottom: none; padding-bottom: 0px; margin-bottom: 0px;">                    native French speaker.                </p>            </li>                                            <li >                <a href="/casting/untitled-comedy-short-41680/justin-159297/">                    Justin  (Lead):                <span class="roletag">                    Male, 20-25, All Ethnicities                </span>                <span class="applyNow"> </span>                </a>                <p class="role-desc"                   style="border-bottom: none; padding-bottom: 0px; margin-bottom: 0px;">                    comedy and improv skills, hopeless romantic.                </p>            </li>                                            <li >                <a href="/casting/untitled-comedy-short-41680/flower-shop-salesperson-159299/">                    Flower Shop Salesperson :                <span class="roletag">                    Males &amp; Females, 30+, All Ethnicities                </span>                <span class="applyNow"> </span>                </a>                <p class="role-desc"                   style="border-bottom: none; padding-bottom: 0px; margin-bottom: 0px;">                    impatient.                </p>            </li>                                            <li >                <a href="/casting/untitled-comedy-short-41680/models-159300/">                    Models  (Supporting):                <span class="roletag">                    Female, 18-35, All Ethnicities                </span>                <span class="applyNow"> </span>                </a>                <p class="role-desc"                   style="border-bottom: none; padding-bottom: 0px; margin-bottom: 0px;">                    small roles, under five lines.                </p>            </li>                            </ul>    </div></div>'
---
/casting/untitled-comedy-short-41680/martinique-159296/
/casting/untitled-comedy-short-41680/justin-159297/
/casting/untitled-comedy-short-41680/flower-shop-salesperson-159299/
/casting/untitled-comedy-short-41680/models-159300/
票数 0
EN

Stack Overflow用户

发布于 2014-11-16 11:23:01

不需要JS解析器!

我假设您知道<script>内容的格式将如示例所示,并且您已经将该标记的内容抓取到一个名为script_text的变量中。

首先,我们需要获取html_role_listing的值,这可以用一个好的正则表达式来完成:

代码语言:javascript
运行
复制
>>> import re
>>> html_role_listing_match = re.search(r'var html_role_listing = \'(.+)\';$', script_text, re.MULTILINE)
>>> html_role_listing = html_role_listing_match.group(1)

然后,我们利用\u003C和类似的转义序列在Python Unicode字符串中也是有效的这一事实(就像它们在JS字符串中有效一样),并使用更安全的eval版本来解析它们

代码语言:javascript
运行
复制
>>> import ast
>>> roles_html = ast.literal_eval("u'%s'" % html_role_listing)

为了证明这一点,您可以检查本文的前几个字符,并查看它们是否已被正确解析:

代码语言:javascript
运行
复制
>>> print roles_html[:10]
<div class

现在,您有了一个可以用BeautifulSoup解析的超文本标记语言字符串:

代码语言:javascript
运行
复制
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup(roles_html)

并获取这些链接的href属性。

代码语言:javascript
运行
复制
>>> links = soup.select('li a')
>>> for link in links:
...     print link.attrs['href']
... 
/casting/untitled-comedy-short-41680/martinique-159296/
/casting/untitled-comedy-short-41680/justin-159297/
/casting/untitled-comedy-short-41680/flower-shop-salesperson-159299/
/casting/untitled-comedy-short-41680/models-159300/
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25170753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档