尝试使用urllib.request时输入错误,'str'对象不可调用

时间:2016-01-21 06:53:04

标签: python request urllib

我遇到了urllopen.rquest的一些问题,我甚至无法确切地说出发生了什么,所以我将提供代码和回溯。首先,代码:

import re as rex
import urllib.request 
import os


#qui ci piazzo le classi per i vari siti

class Amazon:
    def __init__(self,manager,dati):
        self.manager=manager
        self.indirizzo=None
        self.datiAttuali=dati
        self.URLimmagine=None
        self.prezzo=None
        self.speseSped=None

        self.setURLimmagine()
        self.setPrezzoSpese()
        self.caricaDati()



    def setURLimmagine(self):
        patBlocco=rex.compile(r'<div id="imgTagWrapperId"[\s\S]*</div>')
        patUrl=rex.compile(r'http://ecx.images-amazon.com/images/I/[^.]{0,13}')
        blocco=rex.search(patBlocco,self.datiAttuali)
        if blocco==None:
            self.URLimmagine='ND'
        else:
            url=rex.search(patUrl,blocco.group())
            if url!=None:
                self.URLimmagine=url.group()+'.jpg'
            else:
                self.URLimmagine='blocco trovato,ND'

    def setPrezzoSpese(self):
        patBlocco=rex.compile(r'<div class="a-box"[\s\S]*</div>')
        blocco=rex.search(patBlocco,self.datiAttuali)
        if blocco!=None:

            patSpanPrezzo=rex.compile(r'<span class="a-color-price price3P[\s\S]*</span>')
            patSpanSped=rex.compile(r'<span class="a-size-small a-color-secondary shipping3P[\s\S]*</span>')
            spanPrezzo=rex.search(patSpanPrezzo,self.datiAttuali)
            spanSped=rex.search(patSpanSped,self.datiAttuali)
            if spanPrezzo!=None:
                patPrezzoText=rex.compile(r'EUR \w+,\w{0,2}')
                patSpedText=rex.compile(r'(EUR \w+,\w{0,2})|(Spedizione gratuita)')
                prezzoPulito=rex.search(patPrezzoText,spanPrezzo.group()).group()
                spedPulito=rex.search(patSpedText,spanSped.group()).group()
                self.prezzo=prezzoPulito
                self.speseSped=spedPulito
            else:
                patPrezzo=rex.compile(r'(<span id="priceblock_saleprice"[\s\S]*</span>)|(<span id="priceblock_ourprice"[\s\S]*</span>)')
                prezzo=rex.search(patPrezzo,self.datiAttuali)
                if prezzo!=None:
                    patPrezzoRifinito=rex.compile(r'(EUR \w+,\w{0,2})( - )?(EUR \w+,\w{0,2})?')
                    prezzoRifinito=rex.search(patPrezzoRifinito,prezzo.group())
                    prezzoRaffinato=prezzoRifinito.group()
                    self.prezzo=prezzoRaffinato
                    self.speseSped='ND'
                else:
                    self.prezzo='ND'
                    self.speseSped='ND'                

        else:

            patPrezzo=rex.compile(r'<span id="priceblock_ourprice"[\s\S]*</span>')
            prezzo=rex.search(patPrezzo,self.datiAttuali)
            if prezzo!=None:
                patPrezzoPulito=rex.compile(r'rice">[\s\S]{1,21}</span>')
                prezzoPulito=rex.search(patPrezzoPulito,prezzo.group())
                prezzoFinale=prezzoPulito.group()
                patPrezzoRifinito=rex.compile(r'(EUR \w+,\w{0,2})( - )?(EUR \w+,\w{0,2})?')
                prezzoRifinito=rex.search(patPrezzoRifinito,prezzoFinale)
                prezzoRaffinato=prezzoRifinito.group()
                self.prezzo=prezzoRaffinato
                self.speseSped='ND'
            else:
                self.prezzo='ND'
                self.speseSped='ND' 

    def caricaDati(self):
        self.manager.URLimmagine=self.URLimmagine
        self.manager.prezzo=self.prezzo
        self.manager.spedizione=self.speseSped

#qui la classe principale

class DBmanager:
    def __init__(self,nome):
        self.percorso=None
        self.nomeDB=nome
        self.siti={'amazon':lambda self,URL:Amazon(self,dati)}
        self.nomeSito=None #quando verrà passato un URL, per prima cosa verrà pescato il nome del sito, per poter chiamare la
                           #classe adeguata  
        self.ID=None
        self.URL=None
        self.sorgente=None
        self.URLimmagine=None
        self.prezzo=None
        self.spedizione=None
        self.descrizione='descrizione'
        self.contenuti=[]  #qui verranno posizionati gli atomi, creati dopo aver raccolto le info necessarie tramite la classe
                           #apposita


        self.setPercorso()
        self.inizializza(nome)


    def setPercorso(self):
        file=open('config.txt')
        percorso=file.readline()
        file.close()
        self.percorso=percorso[:len(percorso)-1] #questo serve a togliere il \n finale

    def setURL(self,URL):
        self.URL=URL
        pat=rex.compile=r'.+\.(.*)\.'
        trovaNome=rex.search(pat,self.URL)
        self.nomeSito=trovaNome.group(1)
        apri=urllib.request.urlopen(URL)
        self.sorgente=str(apri.read())



    def chiamaSito(self):
        self.siti[self.nomeSito](self,self.sorgente)

    def inizializza(self,nome):
        try:
            file=open(self.percorso+'DATABASE/'+nome+'.adb','r')
            file.close()
        except:
            file=open(self.percorso+'DATABASE/'+nome+'.adb','w')
            file.write('<<0>>\n') #se il file adb non esiste, crealo e scrivi l'ID generale
            file.close()
            os.mkdir(self.percorso+'DATABASE/'+nome) #crea la cartella che conterrà le immagini




def main():
    nome='piripacchio'
    URL=r'http://www.amazon.it/IMMACOLATA-PORCELLANA-SCULTURA-IMMACULATE-INMACULAD/dp/B016APLOEE/ref=sr_1_1?ie=UTF8&qid=1453325779&sr=8-1&keywords=madonna+statua'
    man=DBmanager(nome)
    man.setURL(URL)
    man.chiamaSito()


if __name__=='__main__':
    main()

该程序的想法是用户从亚马逊或其他类似网站输入URL,程序将检索对象的图像,销售价格和(最终)运费。这是通过创建一种简单的数据库来完成的(DBmanager将使用包含数据的一些字典填充self.contenuti列表。现在,DBmanager必须完全相同,无论站点是什么,这都是通过创建具有检索数据的特定功能的特定类(如类Amazon)来实现的(每个站点)有自己的结构,所以我不能使用相同的正则表达式,只需将它们放在字典self.siti中:每当调用self.chiamaSito时,相应的类(这里我只有Amazon )将被称为传递self.sorgente作为参数,这将是提供的站点的内容,转换为str,因此亚马逊类可以通过正则表达式搜索适当的信息。

这是供家庭使用的,我已经创建了一个类似的程序,通过收集的数据,编写一个简单的HTML文件,它是所有感兴趣对象的图像库。我想在这里使用DBmanager来下载图像,以便在我编写GUI时将其显示为tkinter标签。不需要HTML文件,整个过程将基于GUI,就像一种数据库。

问题是,无论我提供什么URL(这里我在main()函数中进行调试,我都会得到这个邪恶而令人讨厌的“东西”:

File "C:\Users\Admin\pyproj\amazons\amazzone2_0.py", line 178, in <module>
  main()
File "C:\Users\Admin\pyproj\amazons\amazzone2_0.py", line 173, in main
  man.setURL(URL)
File "C:\Users\Admin\pyproj\amazons\amazzone2_0.py", line 148, in setURL
  apri=urllib.request.urlopen(URL)
File "C:\Python34\Lib\urllib\request.py", line 153, in urlopen
  return opener.open(url, data, timeout)
File "C:\Python34\Lib\urllib\request.py", line 440, in open
  req = Request(fullurl, data)
File "C:\Python34\Lib\urllib\request.py", line 258, in __init__
  self.full_url = url
File "C:\Python34\Lib\urllib\request.py", line 283, in full_url
  self._full_url, self.fragment = splittag(self._full_url)
File "C:\Python34\Lib\urllib\parse.py", line 952, in splittag
  _tagprog = re.compile('^(.*)#([^#]*)$')

builtins.TypeError: 'str' object is not callable

根据我的理解,问题出在urllib中:由于某种原因,URL未正确解析,我最终得到了错误。所以,我试着写这个:

import urllib.request
sito=urllib.request.urlopen('http://www.amazon.it/Shaving-Factory-rasoio-professionali-singolo/dp/B003DRL6KK/ref=sr_1_2?ie=UTF8&qid=1453313892&sr=8-2&keywords=rasoio')

sorgente=sito.read()


print('yup')

这是在另一个模块中写的,出于测试目的,只有这段代码。如果我拥有它,它可以完美地工作,没有错误。我试过其他网址,同样的事情:如果我尝试第二段代码,没有错误;如果我尝试将其传递给DBmanager,我就会收到错误消息。发生了什么事?

1 个答案:

答案 0 :(得分:2)

您将re.compile()重新绑定到setURL方法中的字符串:

pat=rex.compile=r'.+\.(.*)\.'

这会产生两个分配,一个分配到pat,同一个分配到rex.compile(您将re模块导入为rex)。

你可能打算在那里打电话 re.compile()

pat = rex.compile(r'.+\.(.*)\.')

因为您反弹re.compile 尝试使用该功能的任何其他代码失败并出现相同的异常;你不能叫一个字符串。