花了几天时间写了一个比较完整的爬虫代理模块,基本上实现了一个比较完整的代理系统。
有如下几大模块:
ip来源:http://www.xicidaili.com/wt/ 通过遍历西刺代理中的四个页面获取ip,然后对ip有效性进行检验,将有效的ip写入文件。这里需要注意一下,西刺代理有效的ip一般都在前面,后面基本都是失效了的,我选择每个页面的前30条ip地址来检验,后面的直接舍弃。
#http://www.xicidaili.com/wt/
def get_goubanjia(self,url_target):
try:
#设置headers
headers = {'User-Agent':str(UserAgent().random)}
#发送requests请求
req = requests.get(url_target,headers=headers, timeout=5)
#校正网页编码
req.encoding = req.apparent_encoding
#对网页进行解析
soup = BeautifulSoup(req.text, 'lxml')
tr_list = soup.find_all('tr')
for each in range(1, 31):
print('已经筛选了{}条ip'.format(each))
print("获取地址")
#获取地址
td = tr_list[each].find_all('td')
a = td[1].get_text()
print("获取端口")
#获取端口
b = td[2].get_text()
#将有效的ip写入文件
proxy = 'http://' + a+':'+b
#检验ip是否有效,将有效的ip写入文件当中
if self.verifyIP(proxy):
f = open('ip.txt','a+',encoding='utf-8')
f.write(proxy+'\n')
f.close()
#输出爬取到的信息
print(proxy)
except Exception as e:
print(str(e))
print('{}:网站页面发生变动,请及时更新'.format(url_target))
通过传入的proxy(‘http://123.123.123‘),利用需要爬取的网站作为目标网站,发送requests请求来实现ip有效性的检验。 在检验ip有效性的过程中,我发现了这样一个有趣的现象,同一批ip对不同网站的访问速度不同(排除了网站本身的访问速度原因)。打个比方,有A、B两个网站他们的服务器配置是一样的,但是a、b、c、d四个ip从发送请求到相应这中间的时间却是不一样的。 所以,建议检验ip有效性时采用目标网站比较合适
#验证ip,返回True/False值
def verifyIP(self,proxy):
print('开始判断{}的有效性'.format(proxy))
try:
#设置ip
proxies = {'{}'.format(self.ip_stype):proxy}
#设置headers
headers = {'User-Agent':str(UserAgent().random)}
#发生requests请求
req = requests.get(self.url, headers=headers, proxies=proxies, verify=False, timeout=(6,14))
except Exception as e:
print('{}代理ip无效'.format(proxies))
print('在检验过程中遇到的requests错误原因是:{}'.format(e))
return False
else:
print('{}代理ip有效'.format(proxies))
return True
finally:
print('{}代理ip有效性判断完成'.format(proxies))
删除ip这块相对而言简单一些,读取文件–>删除旧文件–>删除ip列表中的失效ip–>将ip列表写入文件。
#删除proxy
def deleteProxy(self,proxy):
print('删除无效proxy:{}'.format(proxy))
f = open('ip.txt', 'r', encoding='utf-8')
proxy_list = f.readlines()
f.close()
#删除列表中的换行符号
proxy_list = [proxy.replace('\n','') for proxy in proxy_list]
#删除原文件
os.remove('ip.txt')
#删除指定的proxy
proxy_list.remove(proxy)
#当文件为空时,重新下载文件
if len(proxy_list)==0:
print('现在列表为空,我们将重新获取ip')
#调用父类下载新的ip文件
super().getIpFile()
#将信息重新写入文件
f = open('ip.txt', 'a+', encoding='utf-8')
for each in proxy_list:
f.write(each+'\n')
f.close()
简单点来说就是在删除失效ip后检测文件是否为空,为空时,再次从互联网上下载一批新的ip
#删除指定的proxy
proxy_list.remove(proxy)
#当文件为空时,重新下载文件
if len(proxy_list)==0:
print('现在列表为空,我们将重新获取ip')
#调用父类下载新的ip文件
super().getIpFile()
利用while构造一个死循环,只有在requests请求成功时,打破死循环的代码(flag=False)才会被执行,当然每一次循环都会采用新的IP地址以及headers
flag=True
while (flag!=False):
try:
try:
#设置代理ip
proxy = self.createRandomIp()
#设置proxies
proxies = {'{}'.format(self.ip_stype):proxy}
#设置代理headers
headers = {'User-Agent':str(UserAgent().random)}
req = requests.get(self.url, proxies=proxies, headers=headers, verify=False, timeout=(9,21))
flag=False
except Exception as e:
print('上一次请求失败,10秒后我们将进行下一次请求')
print("上一次requests请求失败的原因是{}".format(e))
print('上一次请求的代理ip为:{}'.format(proxy))
time.sleep(10)
#验证proxy的有效性,并对无效proxy进行处理
proxy = self.verifyProxy(proxy)
#设置proxies
proxies = {'{}'.format(self.ip_stype):proxy}
#设置代理headers
headers = {'User-Agent':str(UserAgent().random)}
req = requests.get(self.url, proxies=proxies, headers=headers, verify=False, timeout=(9,21))
flag=False
except:
pass
考虑到短时间多次访问一个网站可能会被识别出来,故在第一次发送requests请求时是不检验ip的有效性,如果请求出错则10秒后会对该ip进行验证,中间间隔10秒是考虑到网络信号的影响。如果检验到ip失效则会将其从ip文件中删除。
在删除失效ip后,会重新分配一个ip并对其有效性进行检验,无效则删除,重新分配ip直至分配的ip通过检验,采用的是递归算法。
在requests请求这一块,也具有相同的思想,不断发送requests请求直至成功,采用while构造死循环。