Python - 从带有链接的网页下载CSV文件

时间:2014-05-04 22:52:30

标签: python csv web download session-cookies

我正在尝试通过python脚本从this page下载CSV文件。

但是当我尝试通过浏览器中的链接直接访问CSV文件时,会显示一个协议表单。在允许我下载文件之前,我必须同意此表单。

无法检索csv文件的确切网址。它是一个发送到后端数据库的值,用于获取文件 - 例如PERIOD_ID=2013-0

  

https://www.paoilandgasreporting.state.pa.us/publicreports/Modules/DataExports/ExportProductionData.aspx?PERIOD_ID=2013-0

我已尝试urllib2.open()urllib2.read(),但它会导致协议格式的html内容,而不是文件内容。

如何编写处理此重定向的python代码,然后将CSV文件提取给我并让我保存在磁盘上?

2 个答案:

答案 0 :(得分:2)

您需要设置ASP.NET_SessionId Cookie。您可以在上下文菜单中使用Chrome的 Inspect element 选项,或使用Firefox和Firebug扩展名来查找。

使用Chrome:

  1. 右键点击网页(在您同意条款后)并选择检查元素
  2. 点击资源 - > 缓存
  3. 选择列表中唯一的元素
  4. 复制ASP.NET_SessionId元素
  5. 使用Firebug:

    1. 右键点击网页(在您同意条款后),然后点击*使用Firebug检查元素
    2. 点击 Cookie
    3. 复制ASP.NET_SessionId元素
    4. 在我的情况下,我得到ihbjzynwfcfvq4nzkncbviou - 它可能适合你,如果不是你需要执行上述程序。

      将Cookie添加到您的请求中,并使用requests模块下载文件(基于answer eladc):

      import requests
      
      cookies = {'ASP.NET_SessionId': 'ihbjzynwfcfvq4nzkncbviou'}
      r = requests.get(
          url=('https://www.paoilandgasreporting.state.pa.us/publicreports/Modules/'
               'DataExports/ExportProductionData.aspx?PERIOD_ID=2013-0'),
          cookies=cookies
      )
      
      with open('2013-0.csv', 'wb') as ofile:
          for chunk in r.iter_content(chunk_size=1024):
              ofile.write(chunk)
              ofile.flush()
      

答案 1 :(得分:1)

这是我的建议,用于自动应用服务器cookie并基本上模仿标准客户端会话行为。

(由@ pope的答案554580无耻地启发。)

import urllib2
import urllib
from lxml import etree

_TARGET_URL = 'https://www.paoilandgasreporting.state.pa.us/publicreports/Modules/DataExports/ExportProductionData.aspx?PERIOD_ID=2013-0'
_AGREEMENT_URL = 'https://www.paoilandgasreporting.state.pa.us/publicreports/Modules/Welcome/Agreement.aspx'
_CSV_OUTPUT = 'urllib2_ProdExport2013-0.csv'


class _MyHTTPRedirectHandler(urllib2.HTTPRedirectHandler):

    def http_error_302(self, req, fp, code, msg, headers):
        print 'Follow redirect...'  # Any cookie manipulation in-between redirects should be implemented here.
        return urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers)

    http_error_301 = http_error_303 = http_error_307 = http_error_302

cookie_processor = urllib2.HTTPCookieProcessor()

opener = urllib2.build_opener(_MyHTTPRedirectHandler, cookie_processor)
urllib2.install_opener(opener)

response_html = urllib2.urlopen(_TARGET_URL).read()

print 'Cookies collected:', cookie_processor.cookiejar

page_node, submit_form = etree.HTML(response_html), {}  # ElementTree node + dict for storing hidden input fields.
for input_name in ['ctl00$MainContent$AgreeButton', '__EVENTVALIDATION', '__VIEWSTATE']:  # Form `input` fields used on the ``Agreement.aspx`` page.
    submit_form[input_name] = page_node.xpath('//input[@name="%s"][1]' % input_name)[0].attrib['value']
    print 'Form input \'%s\' found (value: \'%s\')' % (input_name, submit_form[input_name])

# Submits the agreement form back to ``_AGREEMENT_URL``, which redirects to the CSV download at ``_TARGET_URL``.
csv_output = opener.open(_AGREEMENT_URL, data=urllib.urlencode(submit_form)).read()
print csv_output

with file(_CSV_OUTPUT, 'wb') as f:  # Dumps the CSV output to ``_CSV_OUTPUT``.
    f.write(csv_output)
    f.close()
祝你好运!

[编辑]

关于为什么的事情,我认为@Steinar Lima在要求会话cookie方面是正确的。虽然除非您已经访问了Agreement.aspx页面并通过提供商的网站提交了回复,否则您从浏览器的网络检查员处复制的cookie只会导致另一个重定向到欢迎使用PA DEP Oil& ;气体报告网站欢迎页面。这当然消除了让Python脚本为您完成工作的重点。