Web 抓取 - 如何通过 Angular.js 访问以 JavaScript 呈现的内容?

Posted

技术标签:

【中文标题】Web 抓取 - 如何通过 Angular.js 访问以 JavaScript 呈现的内容?【英文标题】:Web scraping - how to access content rendered in JavaScript via Angular.js? 【发布时间】:2016-05-05 04:40:12 【问题描述】:

我正在尝试从公共站点 asx.com.au 抓取数据

页面http://www.asx.com.au/asx/research/company.do#!/ACB/details 包含一个div 类“view-content”,其中包含我需要的信息:

但是当我尝试通过 Python 的 urllib2.urlopen 查看这个页面时,那个 div 是空的:

import urllib2
from bs4 import BeautifulSoup

url = 'http://www.asx.com.au/asx/research/company.do#!/ACB/details'
page = urllib2.urlopen(url).read()
soup = BeautifulSoup(page, "html.parser")
contentDiv = soup.find("div", "class": "view-content")
print(contentDiv)

# the results is an empty div:
# <div class="view-content" ui-view=""></div>

是否可以通过编程方式访问该 div 的内容?

编辑:根据评论,内容似乎是通过Angular.js 呈现的。是否可以通过 Python 触发该内容的呈现?

【问题讨论】:

我看到 ng-scope - 它是由框架 AngularJS (或类似框架)使用的名称,因此此页面是由 javascript 生成的。 @furas 考虑到这一点,也许这是 ***.com/questions/30673447/… 的副本,我需要使用 Selenium 或类似的? 您不需要 selenium,您已经在我的答案中有 url,您可以使用 urrlibjson 获取它:) 我正在编写代码示例。 @furas 当站点处于生产模式时,您不能使用 ng.probe 【参考方案1】:

此页面使用JavaScript从服务器读取数据并填充页面。

我看到您在 Chrome 中使用开发人员工具 - 请参阅标签 Network 上的 XHRJS 请求。

我找到了这个网址:

http://data.asx.com.au/data/1/company/ACB?fields=primary_share,latest_annual_reports,last_dividend,primary_share.indices&callback=angular.callbacks._0

这个网址几乎以 JSON 格式提供所有数据

但是,如果您使用此链接而不使用 &amp;callback=angular.callbacks._0,那么您将获得纯 JSON 格式的数据,您可以使用 json 模块将其转换为 python 字典。


编辑:工作代码

import urllib2
import json

# new url      
url = 'http://data.asx.com.au/data/1/company/ACB?fields=primary_share,latest_annual_reports,last_dividend,primary_share.indices'

# read all data
page = urllib2.urlopen(url).read()

# convert json text to python dictionary
data = json.loads(page)

print(data['principal_activities'])

输出:

Mineral exploration in Botswana, China and Australia.

编辑(2020.12.23)

这个答案已经有将近 5 年的历史了,是为 Python2 创建的。现在在 Python3 中它需要 urllib.request.urlopen()requests.get() 但真正的问题是 5 年来这个页面改变了结构和技术。网址(问题和答案)不再存在。这个页面需要新的分析和新的方法。

有问题的是网址

http://www.asx.com.au/asx/research/company.do#!/ACB/details

但当前页面使用 url

https://www2.asx.com.au/markets/company/acb

它对AJAX,XHR使用不同的网址

https://asx.api.markitdigital.com/asx-research/1.0/companies/acb/abouthttps://asx.api.markitdigital.com/asx-research/1.0/companies/acb/announcementshttps://asx.api.markitdigital.com/asx-research/1.0/companies/acb/key-statistics 等等

您可以在Chrome/Firefox 中使用DevTools 找到更多网址(标签:Network,过滤器:XHR

import urllib.request
import json

# new url      
url = 'https://asx.api.markitdigital.com/asx-research/1.0/companies/acb/about'

# read all data
page = urllib.request.urlopen(url).read()

# convert json text to python dictionary
data = json.loads(page)

print(data['data']['description'])

输出:

Minerals exploration & development

【讨论】:

非常感谢您快速详细的回复!这太棒了。 在新网址中,您必须使用其他公司名称代替ACB,然后您将获得该公司的数据 XHR 的评论救了我。惊人的。干得好。 @furas 如果被抓取的网站有登录名/密码怎么办,urllib2 将如何处理? @Raj 目前我使用requests 进行抓取。通常,您必须使用登录名/密码发送POST 请求并获取您必须与其他请求一起使用的cookie。出于安全原因,页面还可能发送其他值,因此首先您可能必须获取带有登录表单的页面并获取隐藏值。我总是在 Chrome/Firefox 中以 DevTool 开头,以查看所有请求中的所有值。有时页面使用 JavaScript 生成值,使用可以控制 Web 浏览器的Selenium 更容易完成所有操作。

以上是关于Web 抓取 - 如何通过 Angular.js 访问以 JavaScript 呈现的内容?的主要内容,如果未能解决你的问题,请参考以下文章

我们如何确保 Angular.js 的安全性

使用 Angular JS 抓取网站以获取基本数据(Facebook 之类的链接共享模块)

通过Web Api 和 Angular.js 构建单页面的web 程序

如何保护 Angular.js 或 Ember.js 的 Spring RESTful Web 服务

Angular JS 学习之路由

如何防止 angular.js $http 对象发送 X-Requested-With 标头?