尝试使用 urllib.request 时出现类型错误,'str' 对象不可调用
Type error when trying to use urllib.request, 'str' object is not callable
我在使用 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
都必须表现得完全相同,这是通过创建特定的 classes(如 class Amazon
)来实现的用于检索数据的特定函数(每个站点都有自己的结构,所以我不能使用相同的正则表达式)并简单地将它们放入字典 self.siti
:每当调用 self.chiamaSito
时,适当的 class(这里我只有Amazon
)将被调用传递self.sorgente
作为参数,这将是网站提供的内容,转换成str,所以class Amazon可以通过正则表达式搜索相应的信息。
这是供家庭使用的,我已经创建了一个类似的程序,它利用收集的数据编写了一个简单的 HTML 文件,该文件是所有感兴趣对象的图库。我在这里使用 DBmanager
想做的是下载图像,以便在我编写 GUI 时将其显示到 tkinter 标签中。不需要 HTML 文件,整个东西将基于 GUI,就像一种数据库。
问题是,无论我提供什么 URL(我在 main()
函数中这样做,用于调试目的)我得到这个邪恶和讨厌的 "thing":
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')
这是在另一个模块中写的,为了测试,只有这一段代码。如果我自己拥有它,它可以完美运行,没有错误。我尝试了其他 URLs,同样的事情:如果我尝试第二段代码,没有错误;如果我尝试将它传递给 DBmanager
,我得到了错误。怎么回事?
你re-boundre.compile()
到setURL
方法中的一个字符串:
pat=rex.compile=r'.+\.(.*)\.'
这会产生两个赋值,一个给 pat
,同一个对象给 rex.compile
(您将 re
模块导入为 rex
)。
你可能想打电话给re.compile()
:
pat = rex.compile(r'.+\.(.*)\.')
因为你反弹 re.compile
任何其他代码 尝试使用该函数失败并出现相同的异常;你不能调用字符串。
我在使用 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
都必须表现得完全相同,这是通过创建特定的 classes(如 class Amazon
)来实现的用于检索数据的特定函数(每个站点都有自己的结构,所以我不能使用相同的正则表达式)并简单地将它们放入字典 self.siti
:每当调用 self.chiamaSito
时,适当的 class(这里我只有Amazon
)将被调用传递self.sorgente
作为参数,这将是网站提供的内容,转换成str,所以class Amazon可以通过正则表达式搜索相应的信息。
这是供家庭使用的,我已经创建了一个类似的程序,它利用收集的数据编写了一个简单的 HTML 文件,该文件是所有感兴趣对象的图库。我在这里使用 DBmanager
想做的是下载图像,以便在我编写 GUI 时将其显示到 tkinter 标签中。不需要 HTML 文件,整个东西将基于 GUI,就像一种数据库。
问题是,无论我提供什么 URL(我在 main()
函数中这样做,用于调试目的)我得到这个邪恶和讨厌的 "thing":
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')
这是在另一个模块中写的,为了测试,只有这一段代码。如果我自己拥有它,它可以完美运行,没有错误。我尝试了其他 URLs,同样的事情:如果我尝试第二段代码,没有错误;如果我尝试将它传递给 DBmanager
,我得到了错误。怎么回事?
你re-boundre.compile()
到setURL
方法中的一个字符串:
pat=rex.compile=r'.+\.(.*)\.'
这会产生两个赋值,一个给 pat
,同一个对象给 rex.compile
(您将 re
模块导入为 rex
)。
你可能想打电话给re.compile()
:
pat = rex.compile(r'.+\.(.*)\.')
因为你反弹 re.compile
任何其他代码 尝试使用该函数失败并出现相同的异常;你不能调用字符串。