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,您可以使用 urrlib
和 json
获取它:) 我正在编写代码示例。
@furas 当站点处于生产模式时,您不能使用 ng.probe
【参考方案1】:
此页面使用JavaScript
从服务器读取数据并填充页面。
我看到您在 Chrome
中使用开发人员工具 - 请参阅标签 Network
上的 XHR
或 JS
请求。
我找到了这个网址:
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 格式提供所有数据
但是,如果您使用此链接而不使用 &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 抓取网站以获取基本数据(Facebook 之类的链接共享模块)
通过Web Api 和 Angular.js 构建单页面的web 程序