2015年11月1日 星期日 雨
话说上月写了篇《投票原理 》,投票是管用的,最后利用网上的免费代理给老师投了大概快7w票吧,最后得了第一名,感觉程序员还是能改变世界的。
帮人其实也是帮自己,我帮老师投票之时,其实也是帮自己,至少代理池自己整理出来了三四千条好用的。最近想做一个题库网站/APP,得先抓题库。其实爬虫和投票也差不多,只不过投票可能要求不那么精确,一万票能命中几百票就行,爬虫还是想全部爬下来数据保存的,命中率百分百。
下面是我目前的思路:
-
建立自己的代理池: 可以基于https://github.com/kaito-kidd/proxy-fetcher 这个开源项目改造,先获取代理,再用线程池测试,从而获取自己的代理池。
-
访问网站的函数封装,默认是用代理的。 说明如下: (1)可以用firebug查看访问网页都是header,仿写一下就行。 (2)我访问的网站都需要cookie,所以我加上了cookie的支持。 (3)‘Accept-Encoding’:‘deflate’,这行我是调试过的,如果要支持gzip的话,应该还需要对网站的response再解码,我没有对gzip处理,只写了支持deflate。 (4)UA是每访问一次就变一下,防范于未然。
[code] def icrProxyIndex(self): self.proxyindex += 1 if self.proxyindex >= len(self.proxy)-1: self.proxyindex = 0
def get_url_data(self,url,useProxy=True,localCookieFileName=None): nRetry = 2 while nRetry > 0: try: if useProxy: proxy = self.proxy[self.proxyindex] singleProxyDict = {‘http’:‘http://%s’ % (proxy)} proxyHandler = urllib2.ProxyHandler(singleProxyDict) if localCookieFileName: cj = cookielib.LWPCookieJar(localCookieFileName) cj.save() else: cj = cookielib.CookieJar() proxyAndCookieOpener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj), proxyHandler) urllib2.install_opener(proxyAndCookieOpener)
ua = ‘Mozilla/3.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/%f (KHTML, like Gecko) Chrome/6.0.168.0 Safari/%f’ % (float(self.uaindex)/100,float(self.uaindex)/100)
self.uaindex += 1
headers = {‘Accept’:’text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8’,
‘Accept-Encoding’:‘deflate’,
‘Accept-Language’:‘zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3’,
‘Connection’:‘keep-alive’,
‘User-Agent’: ua,
‘Host’: ‘www.×××××.com’,
}
req = urllib2.Request(url=url,headers=headers)
sock = urllib2.urlopen(req)
htmlSource = sock.read()
sock.close()
return htmlSource
else:
sock = urllib.urlopen(url)
htmlSource = sock.read()
sock.close()
return htmlSource
except urllib2.HTTPError, e:
self.icrProxyIndex()
nRetry -= 1
print e,e.code,self.proxyindex,nRetry
except urllib2.URLError, e:
self.icrProxyIndex()
nRetry -= 1
print e,e.reason,self.proxyindex,nRetry
except Exception,e:
nRetry -= 1
print e,self.proxyindex,nRetry
#print ‘get url fail:%s count=%d e=%s’ % (url,nRetry,e)
#print ‘get url fail:%s’ % (url)
return None
[/code]
-
爬虫程序主题思路: (1)初始化代理池(把本地代理加载到list里,供后面程序调用) (2)对于每条url都应该是能访问的,如果能获取到内容就返回True,否则返回False。 用while 1无限循环保证能抓到为止。 [code]while 1: if fetch() #把能用的代理保存下来,以后优先用这些代理 break[/code]
-
优缺点: 优点:保证每个页面的数据都能抓取下来保存并分类 缺点:单线程轮询效率比较低
总结:在不确定代理是否可用的前提下,我目前只能采取这个方法慢慢爬,还好,我是同时爬几个网站的,慢慢来也没关系。
用线程池分开多段爬应该也是可以的,回头再改造一下,提高效率。
...