【问题标题】:accessing itop database (via oql) with python urllib2使用 python urllib2 访问 itop 数据库(通过 oql)
【发布时间】:2013-11-07 07:09:36
【问题描述】:

我正在尝试通过其通用 Web 界面访问 itop 数据库。我用一个 shell 脚本让它工作:

#!/bin/bash

export http_proxy=''
SERVER=itop-test
SELECT_STATEMENT="SELECT Ticket"

wget -q -O - \
--http-user=myusername \
--http-password=$(cat /home/dummy/private/.passwd) \
"http://${SERVER}.acme.org:8000/webservices/export.php?login_mode=basic&format=csv&expression=${SELECT_STATEMENT}&fields=${FIELDS}"

这会根据需要生成 csv 输出。 现在由于我正在构建的应用程序是在 python 中,我想在 python 中做同样的事情:

#!/usr/bin/python

import csv
import urllib2
import base64


select_statement = 'SELECT Ticket'
fields = ''

itop_server = 'itop-test'
username = 'myusername'
passwd_file = '/home/dummy/private/.passwd'

# extract passwd
password = open(passwd_file,'r').read().replace('\n','')
# clear http_proxy (sometimes set on ACME systems)
proxy_support = urllib2.ProxyHandler({})
opener = urllib2.build_opener(proxy_support)
urllib2.install_opener(opener)

# build url
url = 'http://' + itop_server + \
     '.acme.org:8000/webservices/export.php?login_mode=basic&format=csv&expression='\
     + select_statement + '&fields=' + fields
request = urllib2.Request(url)
base64string = base64.standard_b64encode('%s:%s' % (username, password)).replace('\n', '')
request.add_header('Authorization', 'Basic %s' % base64string)   
result = urllib2.urlopen(request).read()

print result

但是,python 版本不工作,结果包含,除其他外

<p>Error the query can not be executed.</p>
<p>Unexpected token End of Input, found &#039;0&#039; in: <b>S</b>ELECT</p>

我已经检查过使用的 url 是相同的,所以我猜想发送 (?) 的 http 标头肯定存在差异。

这是tcpdump -s 1024 -l -A dst itop-test.acme.org的一些输出

第一个 wget:

..........@..#..2\.P.9..t..GET
/webservices/export.php?login_mode=basic&format=csv&expression=SELECT%20Ticket&fields= HTTP/1.0
User-Agent: Wget/1.12 (linux-gnu)
Accept: */* 
Host: itop-test.acme.org:8000
Connection: Keep-Alive


..........@Q....=..P.9.....GET
/webservices/export.php?login_mode=basic&format=csv&expression=SELECT%20Ticket&fields= HTTP/1.0
User-Agent: Wget/1.12 (linux-gnu)
Accept: */* 
Host: itop-test.acme.org:8000
Connection: Keep-Alive
Authorization: Basic asdfasdfasdfasdf

然后是python

..........@...W.@..P.9.....GET
/webservices/export.php?login_mode=basic&format=csv&expression=SELECT Ticket&fields= HTTP/1.1
Accept-Encoding: identity
Host: itop-test.acme.org:8000
Connection: close
Authorization: Basic asdfasdfasdfasdf
User-Agent: Python-urllib/2.6

我更改了 python 的用户代理,但这没有帮助。我也尝试更改Connection,但没有成功。

对这里发生的事情有任何想法吗?我可以尝试什么来完成这项工作?也许有些人甚至明白发生了什么? :)

编辑 事实证明,curl 也不起作用:

curl --user myusername:$(cat /home/dummy/private/.passwd) \
"http://${SERVER}.acme.org:8000/webservices/export.php?login_mode=basic&format=csv &expression=${SELECT_STATEMENT}&fields=${FIELDS}"

与 python urllib2 的结果相同。我也尝试了 pycurl,但没有成功(与命令行中的 urllib2 和 curl 的结果相同)。

【问题讨论】:

    标签: python curl urllib2 wget pycurl


    【解决方案1】:

    我为 python3 创建了一个库,可以非常轻松地提供您需要的数据。 (通过pip install itoptop安装):

    from itoptop import Itop
    url = 'https://itop_server_name/webservices/rest.php'
    ver = '1.3'
    usr = 'user'
    pwd = 'password'
    itop = Itop(url, ver, usr, pwd)
    ticket = Itop.schema('Ticket')
    
    query_all = {}
    query_from_steve = {'caller_name': 'Steve'}
    
    all_tickets = ticket.find(query_all)
    tickets_from_steve = ticket.find(query_from_steve)
    

    如果您需要 iTop 的特定字段:

    team_name_field = ['team_name']
    team_name_from_all_tickets = ticket.find(query_all, team_name_field)
    
    date_fields = ['start_date', 'end_date']
    tickets_datefields_from_steve = ticket.find({query_from_steve, date_fields)
    

    要将其保存在 csv 中:

    def to_csv(dics, filename, keys=None):
        """
        Create a CSV from a dictionary list
        :param dics: dictionary list
        :param filename: output filename
        :param keys: Optional, subset of keys. Default is all keys.
        :return: None
        """
        if not keys:
            keys = sorted(set().union(*(d.keys() for d in dics)))
    
        import csv
        with open(filename, 'w') as output_file:
            dict_writer = csv.DictWriter(output_file, keys)
            dict_writer.writeheader()
            dict_writer.writerows(dics)
    
    to_csv(all_tickets, 'all_tickets.csv')
    

    如果您需要导入 csv 到 iTop:

    def csv(filename):
        """
        Read CSV and make a dictionary list
        :param filename: csv
        :return: dictionary list
        """
        import csv
        return list(csv.DictReader(open(filename)))
    
    
    all_tickets = csv('all_tickets.csv')
    ticket.insert(all_tickets)
    

    如果您需要更新特定字段:

    update_org_id = {'org_id' = 1}
    ticket.update(query_from_steve, update_org_id)
    

    【讨论】:

      【解决方案2】:

      事实证明,只有 wget 能够将 url 中的空格转换为%20。如果我自己更换它,它可以工作。所以我像这样构建我的网址

      url = 'http://' + itop_server + \
           '.acme.org:8000/webservices/export.php?login_mode=basic&format=xml&expression='\
           + select_statement.replace(' ','%20') + '&fields=' + fields
      

      它会自动替换空格,我仍然可以用空格编写我的选择语句。

      【讨论】:

      • 我建议不要在查询字符串中“手动”编码空格,而是使用专门用于 URL 处理的 python 包:urllib。详情见此帖:stackoverflow.com/a/9345102/5322094
      • 这就是我现在正在做的事情——我很幸运有时间进行重构。 :)
      猜你喜欢
      • 2018-11-13
      • 1970-01-01
      • 2014-11-24
      • 2012-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多