首页 > 解决方案 > Python:在网络中的 javascript 脚本中下载 CSV 列表

问题描述

我想用 python 脚本下载 csv 列表。

http://meteo.navarra.es/estaciones/descargardatos_estacion.cfm?IDEstacion=251

我已经使用此代码来定位文件 url

import urllib.request as urllib2
from bs4 import BeautifulSoup

# Fetch URL
url = 
'http://meteo.navarra.es/estaciones/descargardatos_estacion.cfm? 
IDEstacion=251'
request = urllib2.Request(url)
request.add_header('Accept-Encoding', 'utf-8')

# Response has UTF-8 charset header,
# and HTML body which is UTF-8 encoded
response = urllib2.urlopen(request)

# Parse with BeautifulSoup
soup = BeautifulSoup(response,"html.parser")
print(soup)

这些 CSV 网址位于 javascripts 脚本中

<script type="text/javascript">
<!--

var d = new dTree('d');
d.add(0,-1,'<b>Ficheros de datos</b>');
d.add(1,0,'Ancín INTIA','','','','/js/dtree/img/folder.gif');



    
    d.add(10,1,'Datos diarios','','','','/js/dtree/img/folder.gif');
    
    
        
        d.add(1000,10,'Ancín INTIA_2001.csv','/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2001.csv');
        
        
        
        d.add(1001,10,'Ancín INTIA_2002.csv','/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2002.csv');
        
        
        
        d.add(1002,10,'Ancín INTIA_2003.csv','/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2003.csv');
        
        
        
        d.add(1003,10,'Ancín INTIA_2004.csv','/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2004.csv');
                    
-->

我尝试使用请求和汤来查找 dTree,但我无法访问树属性。

标签: javascriptpythoncsvweb-scrapingbeautifulsoup

解决方案


beautifulsoup 只会将脚本元素的内容作为文本返回,您需要自己从内部提取条目。这可以使用正则表达式来提取.add行来完成。每个文本行都可以使用转换为 Python 列表literal_eval,然后您可以获取最后一个元素。

例如:

import urllib.request as urllib2
from bs4 import BeautifulSoup
import re
from ast import literal_eval

# Fetch URL
url = 'http://meteo.navarra.es/estaciones/descargardatos_estacion.cfm?IDEstacion=251'

request = urllib2.Request(url)
request.add_header('Accept-Encoding', 'utf-8')

# Response has UTF-8 charset header, and HTML body which is UTF-8 encoded
response = urllib2.urlopen(request)

# Parse with BeautifulSoup
soup = BeautifulSoup(response,"html.parser")

re_add = re.compile("add\((.*?\.csv')\);")
csv_files = []

for script in soup.find_all('script', type="text/javascript"):
    if script.string and '.csv' in script.string:
        for entry in re_add.findall(script.string):
            csv_files.append(literal_eval(f'[{entry}]')[-1])

print('\n'.join(csv_files))

给你条目:

/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2001.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2002.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2003.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2004.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2005.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2006.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2007.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2008.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2009.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2010.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2011.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2012.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2013.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2014.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2015.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2016.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2017.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2018.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2019.csv
/_data/datos_estaciones/estacion_251/datos diarios/ancín intia_2020.csv

推荐阅读