准备: 首先,希望学习这篇博文的人具有一定的爬虫知识,或者具备快速学习基础内容的能力,因为有些基础的爬虫知识和内容,需要你们自己加强和掌握,本文基于此基础上,对redis-scrapy框架进行一定的阐述。 环境:python 3.6,linux系统为ubantu 过程: 首先创建项目名称为winnumber,选择好项目的路径后,在终端下输入scrapy startproject winnumber。而后进入项目文件中的spiders文件夹中,创建爬虫文件,执行命令:scrapy genspider -t crawl winnum ‘kaijiang500.com’ 。其中winnum是爬虫文件的名称,后面的域名是我们要爬取彩票信息的网站。
创建好scrapy框架项目后,利用pycharm打开项目文件,会发现winnumber文件夹下有items.py、pipelines.py、settings.py等文件,以及sipders文件夹下的winnum.py爬虫文件。接下来按照顺序一一介绍其内容和作用。
首先是items.py文件,该文件显示了我们的项目需要爬取哪些信息,如双色球的七颗中奖红球 和蓝球。
class WinnumberItem(Item): # define the fields for your item here like: # name = scrapy.Field() date1 = Field() order1 = Field() red1 = Field() red2 = Field() red3 = Field() red4 = Field() red5 = Field() red6 = Field() blue = Field() money = Field() firstPrize = Field() secondPrize = Field()然后完成爬虫文件winnum中的代码编辑,如下代码块中,将前两行代码注释掉,接着换成redis_key保存redis数据库中保存网页的键winnumspider:start_urls,即可实现分布式框架,将简单的scrapy框架改成scrapy-redis分布式框架。这里限于学习,用到的redis数据库可以是ubantu中的。一般的redis框架,是一个集群,将控制爬取的、存储爬取网站网址的队列放在主服务器端的redis数据库中,这里不再赘述。
name = 'winnum' # allowed_domains = ['kaijiang.500.com'] # start_urls = ['http://kaijiang.500.com/shtml/ssq/17020.shtml'] redis_key = "winnumspider:start_urls"如下的代码块中,get_data方法获得彩票的时间信息,get_order显示这是第几期彩票,之后是双色球六颗红球和蓝球的信息,以及每一期的奖池奖金剩余,和一等奖还有二等奖的信息。
def get_data(self,response): data1 = response.xpath("//div[@class='kj_main01']//span[@class='span_right']/text()").extract() if len(data1): data1 = re.findall(u"\d+年\d+月\d+日",data1[0])[0] else: data1 = "NULL" return data1.strip() def get_order(self,response): order1 = response.xpath("//div[@class='kj_main01']//span[@class='span_left']//strong/text()").extract() if len(order1): order1 = order1[0] else: order1 = "NULL" return order1.strip() def get_red1(self,response): red1 = response.xpath("//div[@class='kj_main01']//tr[@align='center']//li[1]/text()").extract() if len(red1): red1 = red1[0] else: red1 = "NULL" return red1.strip() def get_red2(self,response): red2 = response.xpath("//div[@class='kj_main01']//tr[@align='center']//li[2]/text()").extract() if len(red2): red2 = red2[0] else: red2 = "NULL" return red2.strip() def get_red3(self,response): red3 = response.xpath("//div[@class='kj_main01']//tr[@align='center']//li[3]/text()").extract() if len(red3): red3 = red3[0] else: red3 = "NULL" return red3.strip() def get_red4(self,response): red4 = response.xpath("//div[@class='kj_main01']//tr[@align='center']//li[4]/text()").extract() if len(red4): red4 = red4[0] else: red4 = "NULL" return red4.strip() def get_red5(self,response): red5 = response.xpath("//div[@class='kj_main01']//tr[@align='center']//li[5]/text()").extract() if len(red5): red5 = red5[0] else: red5 = "NULL" return red5.strip() def get_red6(self,response): red6 = response.xpath("//div[@class='kj_main01']//tr[@align='center']//li[6]/text()").extract() if len(red6): red6 = red6[0] else: red6 = "NULL" return red6.strip() def get_blue(self,response): blue = response.xpath("//div[@class='kj_main01']//tr[@align='center']//li[7]/text()").extract() if len(blue): blue = blue[0] else: blue = "NULL" return blue.strip() def get_money(self,response): money = response.xpath("//div[@class='kj_main01']//span[@class='cfont1 '][2]/text()").extract() if len(money): money = money[0] else: money = "NULL" return money.strip() def get_firstPrize(self,response): firstPrize = response.xpath("//div[@class='kj_main01']//table[@class='kj_tablelist02']//tr[3]/td[3]/text()").extract() if len(firstPrize): firstPrize = firstPrize[0] else: firstPrize = "NULL" return firstPrize.strip() def get_secondPrize(self,response): secondPrize = response.xpath("//div[@class='kj_main01']//table[@class='kj_tablelist02']//tr[4]/td[3]/text()").extract() if len(secondPrize): secondPrize = secondPrize[0] else: secondPrize = "NULL" return secondPrize.strip()每个方法的参数是response返回的是匹配到的网页内容,而xpath则利用正则表达式的方法抓取相应的内容,在这里推荐使用浏览器的xpath工具,这样可以验证你所抓的内容是否正确,如下所示
利用开发者工具可以查看网页的代码,然后点开xpath工具,就可以用正则表达式匹配网页中的内容,关于正则表达式的相关内容,这里就不赘述了。
好了,既然已经爬取到需要的内容了,接下来就是通过管道文件pipelines保存爬取到的内容,并进行相应的处理。这里我们将爬取到的内容保存为json格式的数据。
class WinnumberPipeline(object): def __init__(self): self.filename = open("winnumber.json","wb") def process_item(self, item, spider): content = json.dumps(dict(item),ensure_ascii=False) + ",\n" self.filename.write(content.encode("utf-8")) return item def close_spider(self,spider): self.filename.close()接下来是配置文件settings,该文件是用来配置相关设置的,该文件的具体使用说明可以参考官方的文档说明,也可以参看其他的博文学习,这里不再赘述。
ITEM_PIPELINES = { 'winnumber.pipelines.WinnumberPipeline': 300, 'scrapy_redis.pipelines.RedisPipeline' : 400, }好了,项目到这里基本完成,接下来你就可以在spiders文件夹下执行命令scrapy crawl winnum来运行爬虫爬取数据了
这是项目的完整代码,放在Github上了,请需要的自行下载 (https://github.com/Taketheone/lotterycrawl_scrapy_redis)
