我编写了一个使用 urllib2 获取 URL 的爬虫。
每隔几个请求我都会遇到一些奇怪的行为,我尝试使用 Wireshark 对其进行分析,但无法理解问题所在。
getPAGE()
负责获取 URL。如果成功获取 URL,则返回 URL 的内容 (response.read()),否则返回 None。
def getPAGE(FetchAddress):
attempts = 0
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0'}
while attempts < 2:
req = Request(FetchAddress, None ,headers)
try:
response = urlopen(req) #fetching the url
except HTTPError, e:
print 'The server didn\'t do the request.'
print 'Error code: ', str(e.code) + " address: " + FetchAddress
time.sleep(4)
attempts += 1
except URLError, e:
print 'Failed to reach the server.'
print 'Reason: ', str(e.reason) + " address: " + FetchAddress
time.sleep(4)
attempts += 1
except Exception, e:
print 'Something bad happened in gatPAGE.'
print 'Reason: ', str(e.reason) + " address: " + FetchAddress
time.sleep(4)
attempts += 1
else:
return response.read()
return None
这是调用getPAGE()
并检查我获取的页面是否有效的函数(检查 -companyID = soup.find('span',id='lblCompanyNumber').string
如果 companyID 为 None 页面无效),如果页面有效,它将汤对象保存到名为 'curRes 的全局变量'。
def isValid(ID):
global curRes
try:
address = urlPath+str(ID)
page = getPAGE(address)
if page == None:
saveToCsv(ID, badRequest = True)
return False
except Exception, e:
print "An error occured in the first Exception block of parseHTML : " + str(e) +' address: ' + address
else:
try:
soup = BeautifulSoup(page)
except TypeError, e:
print "An error occured in the second Exception block of parseHTML : " + str(e) +' address: ' + address
return False
try:
companyID = soup.find('span',id='lblCompanyNumber').string
if (companyID == None): #if lblCompanyNumber is None we can assume that we don't have the content we want, save in the bad log file
saveToCsv(ID, isEmpty = True)
return False
else:
curRes = soup #we have the data we need, save the soup obj to a global variable
return True
except Exception, e:
print "Error while parsing this page, third exception block: " + str(e) + ' id: ' + address
return False
奇怪的行为是——
- 有时 urllib2 执行一个 GET 请求并且不等待它发送下一个 GET 请求的回复(忽略最后一个请求)
- 有时我得到“ [errno 10054] 现有连接被远程主机强行关闭”后代码只是卡住了大约 20 分钟左右等待服务器的响应,而它卡住了我复制 URL 并尝试获取它是手动的,我会在不到 1 秒的时间内得到响应(?)。
- 如果 getPAGE() 函数未能返回 url,它将返回 None 到 isValid(),有时我会收到错误 -
解析此页面时出错,第三个异常块:'NoneType' 对象没有属性 'string' id:....
这很奇怪,因为如果我从 getPAGE() 获得有效结果,我正在创建汤对象,而且汤函数似乎返回 None,每当我尝试运行时都会引发异常
companyID = soup.find('span',id='lblCompanyNumber').string
汤对象永远不应该是无,如果它到达代码的那部分,它应该从 getPAGE() 获取 HTML
我检查并发现问题与第一个问题有某种联系(发送 GET 而不是等待回复,我看到(在 WireShark 上)每次我遇到该异常时,都是针对 urllib2 发送 GET 请求的 url但没有等待响应并继续前进,getPAGE() 应该为该 url 返回 None,但如果它返回 None isValid(ID) 不会通过“if page == None:”条件,我可以'不找出它为什么会发生,这是不可能复制的问题。
我读过 time.sleep() 会导致urllib2 threading 出现问题,所以也许我应该避免使用它?
为什么 urllib2 不总是等待响应(它很少发生不等待的情况)?
“[errno 10054] 现有连接被远程主机强行关闭”错误我该怎么办?顺便说一句 - getPAGE() try: except 块没有捕获异常,它被第一个 isValid() try: except: 块捕获,这也很奇怪,因为 getPAGE() 假设捕获它抛出的所有异常。
try:
address = urlPath+str(ID)
page = getPAGE(address)
if page == None:
saveToCsv(ID, badRequest = True)
return False
except Exception, e:
print "An error occured in the first Exception block of parseHTML : " + str(e) +' address: ' + address
谢谢!