我可以从 highcharts.js 中抓取原始数据吗? - IT屋-程序员软件开发技术分享社区
首页
前端开发
我可以从 highcharts.js 中抓取原始数据吗?
我可以从 highcharts.js 中抓取原始数据吗?
[英] Can I scrape the raw data from highcharts.js?
本文介绍了我可以从 highcharts.js 中抓取原始数据吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我想从使用 highcharts.js
显示图表的页面中抓取数据,因此我完成了对所有页面的解析以到达 下一页 .然而,显示数据集的最后一页使用 highcharts.js
来显示图表,这似乎几乎不可能访问原始数据.
我使用 Python 3.5 和 BeautifulSoup.
还能解析吗?如果是这样,我该如何刮掉它?
解决方案
数据在脚本标签中.您可以使用 bs4 和正则表达式获取脚本标签.您也可以使用正则表达式提取数据,但我喜欢使用 /js2xml 将 js 函数解析为 xml 树:
from bs4 import BeautifulSoup进口请求进口重新导入 js2xml汤 = BeautifulSoup(requests.get("http://www.worldweatheronline.com/brussels-weather-averages/be.aspx").content, "html.parser")脚本 = 汤.find("脚本", text=re.compile("Highcharts.Chart")).text# script = soup.find("script", text=re.compile("precipchartcontainer")).text 如果你想要降水数据解析 = js2xml.parse(脚本)打印 js2xml.pretty_print(解析)
这给了你:
<预><代码><程序><函数调用><功能><标识符名称="$"/></功能><参数><funcexpr><标识符/><参数/><身体><var name="chart"/><函数调用><功能><点访问器><对象><函数调用><功能><标识符名称="$"/></功能><参数><标识符名称=文档"/></参数></函数调用></对象><财产><标识符名称=就绪"/></属性></dotaccessor></功能><参数><funcexpr><标识符/><参数/><身体><assign operator="="><左><标识符名称=图表"/></左><右><新><点访问器><对象><标识符名称="Highcharts"/></对象><财产><标识符名称="图表"/></属性></dotaccessor><参数><对象><属性名称=图表"><对象><属性名称="renderTo"><string>tempchartcontainer</string></属性><属性名称=类型"><string>样条</string></属性></对象></属性><财产名称=信用"><对象><属性名称=启用"><boolean>false</boolean></属性></对象></属性><属性名称=颜色"><阵列><string>#FF8533</string><string>#4572A7</string></阵列></属性><属性名称=标题"><对象><属性名称=文本"><string>布鲁塞尔的平均温度 (°c) 图表</string></属性></对象></属性><属性名称="xAxis"><对象><属性名称=类别"><阵列><string>一月</string><string>二月</string><string>三月</string><string>四月</string><string>可能</string><string>六月</string><string>七月</string><string>八月</string><string>九月</string><string>十月</string><string>十一月</string><string>十二月</string></阵列></属性><属性名称=标签"><对象><属性名称=旋转"><数值=270"/></属性><属性名称=y"><数值=40"/></属性></对象></属性></对象></属性><属性名称="yAxis"><对象><属性名称=标题"><对象><属性名称=文本"><string>温度 (°c)</string></属性></对象></属性></对象></属性><属性名称=工具提示"><对象><属性名称=启用"><boolean>true</boolean></属性></对象></属性><属性名称="plotOptions"><对象><属性名称=样条"><对象><属性名称=数据标签"><对象><属性名称=启用"><boolean>true</boolean></属性></对象></属性><属性名称=启用鼠标跟踪"><boolean>false</boolean></属性></对象></属性></对象></属性><属性名称=系列"><阵列><对象><属性名称=名称"><string>平均高温 (°c)</string></属性><属性名称=颜色"><string>#FF8533</string></属性><属性名称=数据"><阵列><数值=6"/><数值=8"/><数值=11"/><数值=14"/><数值=19"/><数值=21"/><数值=23"/><数值=23"/><数值=19"/><数值=15"/><数值=9"/><数值=6"/></阵列></属性></对象><对象><属性名称=名称"><string>平均低温 (°c)</string></属性><属性名称=颜色"><string>#4572A7</string></属性><属性名称=数据"><阵列><数值=2"/><数值=2"/><数值=4"/><数值=6"/><数值=10"/><数值=12"/><数值=14"/><数值=14"/><数值=11"/><数值=8"/><数值=5"/><数值=2"/></阵列></属性></对象></阵列></属性></对象></参数></新></右></assign>
</funcexpr></参数></函数调用></funcexpr></参数></函数调用></程序>
所以要获取所有数据:
In [28]: from bs4 import BeautifulSoup在 [29]:导入请求在 [30] 中:导入重新在 [31] 中:导入 js2xml在 [32] 中:从 itertools 导入重复在 [33]: from pprint import pprint as pp在 [34]: 汤 = BeautifulSoup(requests.get("http://www.worldweatheronline.com/brussels-weather-averages/be.aspx").content, "html.parser")在 [35] 中:script =soup.find("script", text=re.compile("Highcharts.Chart")).text在 [36] 中:解析 = js2xml.parse(script)在 [37] 中:data = [d.xpath(".//array/number/@value") for d in parsed.xpath("//property[@name='data']")]在 [38] 中:categories = parsed.xpath("//property[@name='categories']//string/text()")在 [39]: output = list(zip(repeat(categories), data))在 [40] 中:pp(输出)[(['一月','二月','行进','四月','可能','六月','七月','八月','九月','十月','十一月','十二月'],['6', '8', '11', '14', '19', '21', '23', '23', '19', '15', '9', '6']),(['一月','二月','行进','四月','可能','六月','七月','八月','九月','十月','十一月','十二月'],['2', '2', '4', '6', '10', '12', '14', '14', '11', '8', '5', '2'])]
就像我说的,你可以只使用正则表达式,但 js2xml 我发现它更可靠,因为错误的空格等不会破坏它.
I want to scrape the data from a page that shows a graph using highcharts.js
, and thus I finished to parse all the pages to get to the following page . However, the last page, the one that displays the dataset, uses highcharts.js
to show the graph, which it seems to be near impossible to access to the raw data.
I use Python 3.5 with BeautifulSoup.
Is it still possible to parse it? If so how can I scrape it?
解决方案
The data is in a script tag. You can get the script tag using bs4 and a regex. You could also extract the data using a regex but I like using /js2xml to parse js functions into a xml tree:
from bs4 import BeautifulSoup
import requests
import re
import js2xml
soup = BeautifulSoup(requests.get("http://www.worldweatheronline.com/brussels-weather-averages/be.aspx").content, "html.parser")
script = soup.find("script", text=re.compile("Highcharts.Chart")).text
# script = soup.find("script", text=re.compile("precipchartcontainer")).text if you want precipitation data
parsed = js2xml.parse(script)
print js2xml.pretty_print(parsed)
That gives you:
<program>
<functioncall>
<function>
<identifier name="$"/>
</function>
<arguments>
<funcexpr>
<identifier/>
<parameters/>
<body>
<var name="chart"/>
<functioncall>
<function>
<dotaccessor>
<object>
<functioncall>
<function>
<identifier name="$"/>
</function>
<arguments>
<identifier name="document"/>
</arguments>
</functioncall>
</object>
<property>
<identifier name="ready"/>
</property>
</dotaccessor>
</function>
<arguments>
<funcexpr>
<identifier/>
<parameters/>
<body>
<assign operator="=">
<left>
<identifier name="chart"/>
</left>
<right>
<new>
<dotaccessor>
<object>
<identifier name="Highcharts"/>
</object>
<property>
<identifier name="Chart"/>
</property>
</dotaccessor>
<arguments>
<object>
<property name="chart">
<object>
<property name="renderTo">
<string>tempchartcontainer</string>
</property>
<property name="type">
<string>spline</string>
</property>
</object>
</property>
<property name="credits">
<object>
<property name="enabled">
<boolean>false</boolean>
</property>
</object>
</property>
<property name="colors">
<array>
<string>#FF8533</string>
<string>#4572A7</string>
</array>
</property>
<property name="title">
<object>
<property name="text">
<string>Average Temperature (°c) Graph for Brussels</string>
</property>
</object>
</property>
<property name="xAxis">
<object>
<property name="categories">
<array>
<string>January</string>
<string>February</string>
<string>March</string>
<string>April</string>
<string>May</string>
<string>June</string>
<string>July</string>
<string>August</string>
<string>September</string>
<string>October</string>
<string>November</string>
<string>December</string>
</array>
</property>
<property name="labels">
<object>
<property name="rotation">
<number value="270"/>
</property>
<property name="y">
<number value="40"/>
</property>
</object>
</property>
</object>
</property>
<property name="yAxis">
<object>
<property name="title">
<object>
<property name="text">
<string>Temperature (°c)</string>
</property>
</object>
</property>
</object>
</property>
<property name="tooltip">
<object>
<property name="enabled">
<boolean>true</boolean>
</property>
</object>
</property>
<property name="plotOptions">
<object>
<property name="spline">
<object>
<property name="dataLabels">
<object>
<property name="enabled">
<boolean>true</boolean>
</property>
</object>
</property>
<property name="enableMouseTracking">
<boolean>false</boolean>
</property>
</object>
</property>
</object>
</property>
<property name="series">
<array>
<object>
<property name="name">
<string>Average High Temp (°c)</string>
</property>
<property name="color">
<string>#FF8533</string>
</property>
<property name="data">
<array>
<number value="6"/>
<number value="8"/>
<number value="11"/>
<number value="14"/>
<number value="19"/>
<number value="21"/>
<number value="23"/>
<number value="23"/>
<number value="19"/>
<number value="15"/>
<number value="9"/>
<number value="6"/>
</array>
</property>
</object>
<object>
<property name="name">
<string>Average Low Temp (°c)</string>
</property>
<property name="color">
<string>#4572A7</string>
</property>
<property name="data">
<array>
<number value="2"/>
<number value="2"/>
<number value="4"/>
<number value="6"/>
<number value="10"/>
<number value="12"/>
<number value="14"/>
<number value="14"/>
<number value="11"/>
<number value="8"/>
<number value="5"/>
<number value="2"/>
</array>
</property>
</object>
</array>
</property>
</object>
</arguments>
</new>
</right>
</assign>
</body>
</funcexpr>
</arguments>
</functioncall>
</body>
</funcexpr>
</arguments>
</functioncall>
</program>
So to get all the data:
In [28]: from bs4 import BeautifulSoup
In [29]: import requests
In [30]: import re
In [31]: import js2xml
In [32]: from itertools import repeat
In [33]: from pprint import pprint as pp
In [34]: soup = BeautifulSoup(requests.get("http://www.worldweatheronline.com/brussels-weather-averages/be.aspx").content, "html.parser")
In [35]: script = soup.find("script", text=re.compile("Highcharts.Chart")).text
In [36]: parsed = js2xml.parse(script)
In [37]: data = [d.xpath(".//array/number/@value") for d in parsed.xpath("//property[@name='data']")]
In [38]: categories = parsed.xpath("//property[@name='categories']//string/text()")
In [39]: output = list(zip(repeat(categories), data))
In [40]: pp(output)
[(['January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'],
['6', '8', '11', '14', '19', '21', '23', '23', '19', '15', '9', '6']),
(['January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'],
['2', '2', '4', '6', '10', '12', '14', '14', '11', '8', '5', '2'])]
Like I said you could just use a regex but js2xml I find is more reliable as erroneous spaces etc.. won't break it.
这篇关于我可以从 highcharts.js 中抓取原始数据吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文