简单介绍
pi:
简单介绍下,我们需要用到的技术,python 版本是用的pyhon3,系统环境是linux,开发工具是vscode;工具包:request 爬取页面数据,然后redis 实现数据缓存,lxml 实现页面数据的分析,提取我们想要的数据,然后多线程和多进程提升爬取速度,最后,通过celery 框架实现分布式爬取,并实际部署下,下面就按这个逻辑顺序,进行介绍
request爬取页面数据
开发环境的的安装这里就不介绍了,大家可以在 去搜索下其他的博客,这类文章很多
第一步:通过pip 安装 request: pip install requests;
我们可以通过help(requests),查看下requests一些基本信息:
可以看到这里有两个方法一个get,一个post,post主要是一些需要提交表单的url,我们这里主要使用get方法,看下实际的代码吧:
resp = requests.get(url,headers=header,proxies=proxie,timeout=self.timeOut)
html = resp.text #text 属性获取具体的html文本
#小于400表示成功了
if resp.status_code >=400:
html = None
#500到600需要重试 400到500是可以直接退出的错误
if 600> resp.status_code >500 and self.numTry:
self.numTry -= 1
#递归 实现错误重试
return self.download(url,header,proxie)
except requests.exceptions.RequestException as e:
return {'html':None,'code':500}
return {'html':html,'code':resp.status_code}
resp 是访问网页响应实体,text属性是网页的文本内容,status_code 访问网站状态吗,可以通过它来判断访问网页是失败,还是成功,以及是否需要重试,还是不需要重试的报错;
像下载网页的具体内容,这种都是所有爬虫都是一样的,我们完全可以单独写一个类或者一个方法,以实现复用,这里我推荐,写个回调类,方便我们后面扩展,以及存储一些关键的信息,例如:缓存、代理、header
在实现这个类,之前我们下介绍下缓存,代理的实现;
代理
代理实现起来比较简单,request提供了很好的支持,只要给get()方法的proxies关键字参数,传一个代理队列就行resp = requests.get(url,headers=header,proxies=proxie,timeout=self.timeOut)
缓存
缓存需要重点介绍下,我们需要用到redis,redis的安装教程,推荐到菜鸟驿站去学习;
安装号redis服务器后,还需要安装python使用redis的模块, 直接pip安装就可以,pip install redis
,我们通过 url -> html文本的方式存储我们访问过的网页,然后直接上代码:
import json
import zlib
from redis import StrictRedis
from datetime import timedelta
class RedisCache:
#是否压缩文件 compress endcoding 编码方式,key:url value:html redis链接:client 设置缓存过期时间expires=timedelta(days=30)
def __init__(self,client=None,compress=True,endcoding='utf-8',expires=timedelta(days=30)):
self.client = StrictRedis(host='localhost',port=6379,db=0)
self.compress = True
self.endcoding =endcoding
self.expires = expires
#序列化 解压 解码 序列化
def __getitem__(self,url):
value = self.client.get(url)
if value:
if self.compress:
value = zlib.decompress(value)
return json.loads(value.decode(self.endcoding))
else:
raise KeyError(url+'does exit')
#反序列化 解码 解压
def __setitem__(self,url,html):
data = bytes(json.dumps(html),encoding=self.endcoding)
if self.compress:
data = zlib.compress(data)
#设置过期时间 setex
self.client.setex(url,self.expires,data)
这里我们还通过zilb模块对我们的代码进行了压缩,这是为了节省空间,因为redis是报内容存到