【问题标题】:Extracting data from a URL result with special formatting从具有特殊格式的 URL 结果中提取数据
【发布时间】:2011-05-02 15:58:40
【问题描述】:

我有一个网址:
http://somewhere.com/relatedqueries?limit=2&query=seedterm

修改输入、限制和查询将生成所需数据。限制是可能的最大项数,查询是种子项。

URL 提供格式如下的文本结果:
oo.visualization.Query.setResponse({version:'0.5',reqId:'0',status:'ok',sig:'1303596067112929220',table:{cols:[{id:'score',label:'Score ',type:'number',pattern:'#,##0.###'},{id:'query',label:'Query',type:'string',pattern:''}],rows :[{c:[{v:0.9894380670262618,f:'0.99'},{v:'newterm1'}]},{c:[{v:0.9894380670262618,f:'0.99'},{v:'newterm2' }]}],p:{'totalResultsCount':'7727'}}});

我想编写一个带有两个参数(限制数和查询种子)的 python 脚本,去在线获取数据,解析结果并返回一个包含新术语的列表 ['newterm1','newterm2' ] 在这种情况下。

我希望得到一些帮助,尤其是在获取 URL 方面,因为我以前从未这样做过。

【问题讨论】:

    标签: python parsing url


    【解决方案1】:

    我不太了解您的问题,因为从您那里的代码看来,您使用的是Visualization API(顺便说一句,这是我第一次听说)。

    但是,如果您只是在寻找一种从网页获取数据的方法,您可以使用 urllib2 这只是为了获取数据,如果您想解析检索到的数据,您将不得不使用更合适的像BeautifulSoop这样的库

    如果你正在处理另一个 Web 服务(RSS、Atom、RPC)而不是网页,你可以找到一堆你可以使用的 Python 库,它们可以完美地处理每个服务。

    import urllib2
    
    from BeautifulSoup import BeautifulSoup
    
    result =  urllib2.urlopen('http://somewhere.com/relatedqueries?limit=%s&query=%s' % (2, 'seedterm'))
    
    htmletxt = resul.read()
    
    result.close()
    
    soup = BeautifulSoup(htmltext, convertEntities="html" )
    
    # you can parse your data now check BeautifulSoup API.
    

    【讨论】:

      【解决方案2】:

      听起来你可以把这个问题分解成几个子问题。

      子问题

      在编写完整的脚本之前需要解决一些问题:

      1. 形成请求 URL: 从模板创建配置的请求 URL
      2. 检索数据:实际发出请求
      3. Unwrapping JSONP:返回的数据似乎是 JSON 包装在 JavaScript 函数调用中
      4. 遍历对象图:浏览结果以找到所需的信息位

      形成请求 URL

      这只是简单的字符串格式化。

      url_template = 'http://somewhere.com/relatedqueries?limit={limit}&query={seedterm}'
      url = url_template.format(limit=2, seedterm='seedterm')
      

      Python 2 笔记

      您需要在此处使用字符串格式化运算符 (%)。

      url_template = 'http://somewhere.com/relatedqueries?limit=%(limit)d&query=%(seedterm)s'
      url = url_template % dict(limit=2, seedterm='seedterm')
      

      检索数据

      您可以为此使用内置的 urllib.request 模块。

      import urllib.request
      data = urllib.request.urlopen(url) # url from previous section
      

      这将返回一个名为data 的类似文件的对象。您也可以在此处使用 with 语句:

      with urllib.request.urlopen(url) as data:
          # do processing here
      

      Python 2 笔记

      导入urllib2 而不是urllib.request。

      解开 JSONP

      您粘贴的结果类似于 JSONP。鉴于被调用的包装函数 (oo.visualization.Query.setResponse) 没有改变,我们可以简单地去掉这个方法调用。

      result = data.read()
      
      prefix = 'oo.visualization.Query.setResponse('
      suffix = ');'
      
      if result.startswith(prefix) and result.endswith(suffix):
          result = result[len(prefix):-len(suffix)]
      

      解析 JSON

      生成的 result 字符串只是 JSON 数据。使用内置的 json 模块解析它。

      import json
      
      result_object = json.loads(result)
      

      遍历对象图

      现在,您有一个代表 JSON 响应的 result_object。对象本身是一个dict,带有version、reqId 等键。根据您的问题,您需要执行以下操作来创建您的列表。

      # Get the rows in the table, then get the second column's value for
      # each row
      terms = [row['c'][2]['v'] for row in result_object['table']['rows']]
      

      把它们放在一起

      #!/usr/bin/env python3
      
      """A script for retrieving and parsing results from requests to
      somewhere.com.
      
      This script works as either a standalone script or as a library. To use
      it as a standalone script, run it as `python3 scriptname.py`. To use it
      as a library, use the `retrieve_terms` function."""
      
      import urllib.request
      import json
      import sys
      
      E_OPERATION_ERROR = 1
      E_INVALID_PARAMS = 2
      
      def parse_result(result):
          """Parse a JSONP result string and return a list of terms"""
          prefix = 'oo.visualization.Query.setResponse('
          suffix = ');'
      
          # Strip JSONP function wrapper
          if result.startswith(prefix) and result.endswith(suffix):
              result = result[len(prefix):-len(suffix)]
      
          # Deserialize JSON to Python objects
          result_object = json.loads(result)
      
          # Get the rows in the table, then get the second column's value
          # for each row
          return [row['c'][2]['v'] for row in result_object['table']['rows']]
      
      def retrieve_terms(limit, seedterm):
          """Retrieves and parses data and returns a list of terms"""
          url_template = 'http://somewhere.com/relatedqueries?limit={limit}&query={seedterm}'
          url = url_template.format(limit=limit, seedterm=seedterm)
      
          try:
              with urllib.request.urlopen(url) as data:
                  data = perform_request(limit, seedterm)
                  result = data.read()
          except:
              print('Could not request data from server', file=sys.stderr)
              exit(E_OPERATION_ERROR)
      
          terms = parse_result(result)
          print(terms)
      
      def main(limit, seedterm):
          """Retrieves and parses data and prints each term to standard output"""
          terms = retrieve_terms(limit, seedterm)
          for term in terms:
              print(term)
      
      if __name__ == '__main__'
          try:
              limit = int(sys.argv[1])
              seedterm = sys.argv[2]
          except:
              error_message = '''{} limit seedterm
      
      limit must be an integer'''.format(sys.argv[0])
              print(error_message, file=sys.stderr)
              exit(2)
      
          exit(main(limit, seedterm))
      

      Python 2.7 版本

      #!/usr/bin/env python2.7
      
      """A script for retrieving and parsing results from requests to
      somewhere.com.
      
      This script works as either a standalone script or as a library. To use
      it as a standalone script, run it as `python2.7 scriptname.py`. To use it
      as a library, use the `retrieve_terms` function."""
      
      import urllib2
      import json
      import sys
      
      E_OPERATION_ERROR = 1
      E_INVALID_PARAMS = 2
      
      def parse_result(result):
          """Parse a JSONP result string and return a list of terms"""
          prefix = 'oo.visualization.Query.setResponse('
          suffix = ');'
      
          # Strip JSONP function wrapper
          if result.startswith(prefix) and result.endswith(suffix):
              result = result[len(prefix):-len(suffix)]
      
          # Deserialize JSON to Python objects
          result_object = json.loads(result)
      
          # Get the rows in the table, then get the second column's value
          # for each row
          return [row['c'][2]['v'] for row in result_object['table']['rows']]
      
      def retrieve_terms(limit, seedterm):
          """Retrieves and parses data and returns a list of terms"""
          url_template = 'http://somewhere.com/relatedqueries?limit=%(limit)d&query=%(seedterm)s'
          url = url_template % dict(limit=2, seedterm='seedterm')
      
          try:
              with urllib2.urlopen(url) as data:
                  data = perform_request(limit, seedterm)
                  result = data.read()
          except:
              sys.stderr.write('%s\n' % 'Could not request data from server')
              exit(E_OPERATION_ERROR)
      
          terms = parse_result(result)
          print terms
      
      def main(limit, seedterm):
          """Retrieves and parses data and prints each term to standard output"""
          terms = retrieve_terms(limit, seedterm)
          for term in terms:
              print term
      
      if __name__ == '__main__'
          try:
              limit = int(sys.argv[1])
              seedterm = sys.argv[2]
          except:
              error_message = '''{} limit seedterm
      
      limit must be an integer'''.format(sys.argv[0])
              sys.stderr.write('%s\n' % error_message)
              exit(2)
      
          exit(main(limit, seedterm))
      

      【讨论】:

      • 无论如何要使该脚本在 2.7 中工作?我也认为它需要'main':
      • 此脚本是为与 Python 3 一起工作而编写的。我将在答案中添加注释,说明如何在 Python 2 上使用它。
      猜你喜欢
      • 2017-02-24
      • 2021-04-04
      • 1970-01-01
      • 1970-01-01
      • 2018-10-31
      • 1970-01-01
      • 2022-07-08
      • 2016-05-30
      • 1970-01-01
      相关资源
      最近更新 更多