【问题标题】:Elegant way to split an xpath output into two variables to insert it into a database将 xpath 输出拆分为两个变量以将其插入数据库的优雅方法
【发布时间】:2012-08-03 16:20:05
【问题描述】:

我们有一段代码可以从我们的 tomcat 服务器中提取服务列表并将其插入到数据库中。基本上,代码将从具有以下结构的 html 结果中接收大量输出(100+ 个结果):

<TABLE bgcolor=#dddddd border=1>
<TR>
<TD valign="top"><B>name</B></TD>
<TD>Loader</TD>
</TR>
<TR>
<TD valign="top"><B>enabled</B></TD>
<TD>true</TD>
</TR>
<TR>
<TD valign="top"><B>loadok</B></TD>
<TD>13</TD>
</TR>
</TABLE>
<TABLE bgcolor=#dddddd border=1>
<TR>
<TD valign="top"><B>name</B></TD>
<TD>tester</TD>
</TR>
<TR>
<TD valign="top"><B>enabled</B></TD>
<TD>false</TD>
</TR>
<TR>
<TD valign="top"><B>loadok</B></TD>
<TD>13</TD>
</TR>
</TABLE>

以下是实际代码(有效)

#!/usr/bin/env python

import psycopg2
import urllib2
import base64
import sys
import re
import lxml.html as LH

con = None

try:

    con = psycopg2.connect(database='xx', user='xx',password='xx',host='vxx')
    cur = con.cursor()
    qry ="select iservers.env,iservers.family,iservers.prefix,iservers.iserver,iservers.login,iservers.password,services.service,"   +\
    "proxy_access.proxy_server,proxy_access.proxy_user,proxy_access.proxy_pass "        +\
    "from services,iservers,proxy_access where iservers.env='TEST' and services.id='2' "
    cur.execute(qry)
    data = cur.fetchall()

    for result in data:
    
        env      = result[0]
        family   = result[1]
        prefix   = result[2]
        iserver  = result[3]
        login    = result[4]
        password = result[5]
        service  = result[6]
        proxyHost = result[7]
        proxyUser = result[8]
        proxyPass = result[9]

        proxy_auth = "http://"+proxyUser+":"+proxyPass+"@"+proxyHost
        proxy_handler = urllib2.ProxyHandler({"http": proxy_auth})

        opener = urllib2.build_opener(proxy_handler)
        urllib2.install_opener(opener)
        request = urllib2.Request("http://"+iserver+service)
        base64string = base64.encodestring('%s:%s' % (login, password)).replace('\n', '')
        request.add_header("Authorization", "Basic %s" % base64string)
        response = urllib2.urlopen(request)
        html = response.read()
        
        ###################### CHANGE THIS TO USE A HTML PARSER
        regex = r"name</B></TD>\s<TD>(.*?)</TD>\s</TR>\s<TR>\s(.*)enabled</B></TD>\s<TD>(.*)</TD>"
        for m in re.finditer(regex,html):
            print "inserting\t"+iserver+"\t"+m.group(1)
            cur.execute("INSERT INTO pereirtc.package_status (env,family,iserver,prefix,package,status) values (%s,%s,%s,%s,%s,%s)",(env,family,iserver,prefix,m.group(1),m.group(3)))
            con.commit()
        ###################### END
except psycopg2.DatabaseError, e:
    print 'Error %s' % e
    sys.exit(1)

finally:

    if con:
        con.close()
        

在 Stack Overflow 的帮助下,有人建议我将“更改此 ....”上的块更改为 libxml。所以我得到了以下块来使用:

  doc = LH.fromstring(html)
  tds = (td.text_content() for td in doc.xpath("//td"))
  for td, val in zip(*[tds]*2):
      if td in ("name","enabled"):
          print (td,val)
      

通过上面的例子,我得到了结果:

('name', 'Loader')
('enabled', 'true')

我想要的是,使用 xpath 将结果插入数据库。由于我是从 python 开始的,所以我无法使用 xpath/libxml 来做到这一点。

【问题讨论】:

    标签: python database xpath lxml libxml2


    【解决方案1】:

    我不确定你的意思是不是下面的简单操作,但是将结果分成两个变量是这样实现的:

    doc = LH.fromstring(html)
    tds = (td.text_content() for td in doc.xpath("//td"))
    for td, val in zip(*[tds]*2):
        if td == "name":
            name = val
        elif td == "enabled":
            enabled = val
    
    print name
    print enabled
    

    【讨论】:

    • 嗨,我尝试了您的解决方案,只返回了 4 个结果(总共 120 个)如果我将打印名称/启用放在 for 循环中,我会收到错误“NameError: name 'name' is not defined "
    • 嗨,在 if 条件中插入打印后,您的解决方案工作了:)
    【解决方案2】:

    我猜:

    blah = [('name', 'Loader'), ('enabled', 'true')]
    blahd = dict(blah)
    cursor.execute('insert into blah (name, enabled) values(%(name)s, %(enabled)s)', blahd)
    

    或者,不使用命名值...:

    cursor.execute('insert into blah (name, enabled) values(?, ?)', [i[1] for i in blah])
    

    【讨论】:

    • 我忘了告诉名称中的值,并且启用是动态的。它的服务列表。任何方式使 Loader 和 true from blah = [('name', 'Loader'), ('enabled', 'true')] 从 td 接收值?
    • @ThalesPereira 错误,那么您的数据库架构是什么?
    • 然后创建一个带有 PACKAGE 和 STATUS 的元组/序列作为我所谓的 blah 的第二个元素......或者,如果 DBAPI 有 .executemany 方法,使用它......跨度>
    • 对于第一个 sugestion,我得到了 100 个相同值的插入( loader, true ),对于第二个 sugestion 它返回了错误: Error syntax error at or near "," LINE 1: ... into pereirtc.package_status(包,状态)值(?,?)
    • @Thales 第一次,您循环遍历对象列表并执行插入,对吗?
    猜你喜欢
    • 2019-04-08
    • 2017-02-25
    • 2014-01-12
    • 1970-01-01
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 2019-01-27
    • 1970-01-01
    相关资源
    最近更新 更多