python爬虫 之 scrapy框架采集2000期彩票数据

python爬虫 之 scrapy框架采集2000期彩票数据

最近学习一下数据分析,需要大量的数据,不知道搞啥好就用scrapy框架爬2000期的彩票双色球,看看哪个号码出现的机率大一些。
第一步:

  1. 在终端切换到想要新建爬虫文件的目录下利用 cd XXXX 进行切换 在这里插入图片描述

  2. 输入scrapy startproject 文件名 ,并利用cd 文件名 切换到新建目录!在这里插入图片描述
    我这里新建了一个项目叫gansha 这里成功了就可以看到提示输入cd gansha 进入到项目中

  3. 输入scrapy genspider 爬虫名 www.XXXXX.com 创建一个爬虫文件,后面的网址可以随便写到时候进入爬虫文件里面可以改。 我这里创建了一个叫ganshane的爬虫文件。在这里插入图片描述
    看到这个就说明已经创建好了。我们可以在目录里面看到在这里插入图片描述
    这里 gansha 是项目名 里面包含

    1. spiders (里面包含用户自己写的爬虫代码,用的最多),
    2. int.py (基本上用不着 不管),
    3. items.py (items代码模块,持久化储存用的),
    4. middlewares.py (中间件,作用很多UA伪装,代理设置,scrapy结合selenium需要在这里拦截请求然后让 selenium请求url并返回数据。。。等等),
    5. pipelines.py(管道 pipelines代码模块),
    6. setings.py(配置文件)

这个是演示流程随便建的一个,我实际创建的是这个在这里插入图片描述

第二步:点击capa.py 打开文件,写爬虫代码

  1. 进入页面
    在这里插入图片描述
    发现数据都在 tebody 下的 tr 标签里面但是第一个 tr 和第二个 tr 标签是表头的一些信息是我不要的,最后一个tr标签里面是页面信息也不是我要的所以要剔除
    所以用xpath解析到
#拿到有效数据的tr标签列表
#xpath解析式不能有‘tebody’ 
#[2:-1]剔除掉不要的tr标签
tr_list = response.xpath('/html/body/table//tr')[2:-1]
# 遍历列表拿到数据
for tr in tr_list:
    day = tr.xpath('./td[1]/text()')[0].extract() #在scrapy里面xpath解析要拿到数据后面都要加上.extract()
    center = tr.xpath('./td[2]/text()')[0].extract()#也可以写成extract_first()
    red1 = tr.xpath('./td[3]/em[1]/text()')[0].extract()
    red2 = tr.xpath('./td[3]/em[2]/text()')[0].extract()
    red3 = tr.xpath('./td[3]/em[3]/text()')[0].extract()
    red4 = tr.xpath('./td[3]/em[4]/text()')[0].extract()
    red5 = tr.xpath('./td[3]/em[5]/text()')[0].extract()
    red6 = tr.xpath('./td[3]/em[6]/text()')[0].extract()
    blue = tr.xpath('./td[3]/em[7]/text()')[0].extract()
    # 这里就拿到了一页的全部期号和双色球的号码
  1. 首页 url = ‘http://kaijiang.zhcw.com/zhcw/inc/ssq/ssq_wqhg.jsp?pageNum=1’
    第二页url = ‘http://kaijiang.zhcw.com/zhcw/inc/ssq/ssq_wqhg.jsp?pageNum=2’ 很容易分析出规律
    所以
url = 'http://kaijiang.zhcw.com/zhcw/inc/ssq/ssq_wqhg.jsp?pageNum={}'
n = 1
while n <= 132:
   new_url = url.format(n)
   n += 1
   #绑定回调到解析的函数就可以拿到所有的数据

spider代码:

import scrapy
from caipiaopa.items import CaipiaopaItem  #


class CapaSpider(scrapy.Spider):
    name = 'capa'
    # allowed_domains = ['www.cc.com']
    start_urls = ['http://kaijiang.zhcw.com/zhcw/inc/ssq/ssq_wqhg.jsp?pageNum=1'] #起始页url
    url = 'http://kaijiang.zhcw.com/zhcw/inc/ssq/ssq_wqhg.jsp?pageNum=1{}' 
    page = 2
    def parse(self, response):
        tr_list = response.xpath('/html/body/table//tr')[2:-1]
        for tr in tr_list:
            day = tr.xpath('./td[1]/text()')[0].extract()
            center = tr.xpath('./td[2]/text()')[0].extract()
            red1 = tr.xpath('./td[3]/em[1]/text()')[0].extract()
            red2 = tr.xpath('./td[3]/em[2]/text()')[0].extract()
            red3 = tr.xpath('./td[3]/em[3]/text()')[0].extract()
            red4 = tr.xpath('./td[3]/em[4]/text()')[0].extract()
            red5 = tr.xpath('./td[3]/em[5]/text()')[0].extract()
            red6 = tr.xpath('./td[3]/em[6]/text()')[0].extract()
            blue = tr.xpath('./td[3]/em[7]/text()')[0].extract()

        while self.page <= 132:
            new_url = self.url.format(self.page)
            self.page += 1
            yield scrapy.Request(new_url, callback=self.parse) #绑定回调(自己)

这里只是解析出了数据,还没有持久化存储

第三步:将解析到的数据封装储存在item类型对象中。

  1. 点开 items.py 。
  2. 在class CaipiaopaItem(scrapy.Item): 里定义我们解析出来的数据字段,将其定义为item对象的属性
class CaipiaopaItem(scrapy.Item):
    day = scrapy.Field()
    center = scrapy.Field()
    red1 = scrapy.Field()
    red2 = scrapy.Field()
    red3 = scrapy.Field()
    red4 = scrapy.Field()
    red5 = scrapy.Field()
    red6 = scrapy.Field()
    blue = scrapy.Field()
  1. 再打开爬虫文件 把item类导入 ,并实例化item类型对象,将数据提交。
    spider 完整代码:
import scrapy
from caipiaopa.items import CaipiaopaItem


class CapaSpider(scrapy.Spider):
    name = 'capa'
    # allowed_domains = ['www.cc.com']
    start_urls = ['http://kaijiang.zhcw.com/zhcw/html/ssq/list_1.html']
    url = 'http://kaijiang.zhcw.com/zhcw/html/ssq/list_{}.html'
    page = 2

    def parse(self, response):
        item = CaipiaopaItem() #实例化item类型对象
        tr_list = response.xpath('/html/body/table//tr')[2:-1]
        for tr in tr_list:
            day = tr.xpath('./td[1]/text()')[0].extract()
            center = tr.xpath('./td[2]/text()')[0].extract()
            red1 = tr.xpath('./td[3]/em[1]/text()')[0].extract()
            red2 = tr.xpath('./td[3]/em[2]/text()')[0].extract()
            red3 = tr.xpath('./td[3]/em[3]/text()')[0].extract()
            red4 = tr.xpath('./td[3]/em[4]/text()')[0].extract()
            red5 = tr.xpath('./td[3]/em[5]/text()')[0].extract()
            red6 = tr.xpath('./td[3]/em[6]/text()')[0].extract()
            blue = tr.xpath('./td[3]/em[7]/text()')[0].extract()
            item['day'] = day   #数据封装储存在item类型对象中
            item['center'] = center
            item['red1'] = red1
            item['red2'] = red2
            item['red3'] = red3
            item['red4'] = red4
            item['red5'] = red5
            item['red6'] = red6
            item['blue'] = blue
            yield item  #将数据提交给管道

        while self.page <= 132:
            new_url = self.url.format(self.page)
            self.page += 1
            yield scrapy.Request(new_url, callback=self.parse)

第四步:在管道里接收item封装的数据,并持久化存储。

  1. 点开 pipelines.py 写入持久化存储的方法
  2. 这里我定义了两个类把数据一份存储在本地csv文件,一份存入MYSQL数据库中
from itemadapter import ItemAdapter
import pymysql #导包


class CaipiaopaPipeline: #存储到本地csv文件
    fp = None  
    def open_spider(self,spider): #避免打开文件多次
        self.fp = open('./2000期彩票.csv', 'w', encoding='utf-8')
    def process_item(self, item, spider):
        day = item['day']
        center = item['center']
        red1 = item['red1']
        red2 = item['red2']
        red3 = item['red3']
        red4 = item['red4']
        red5 = item['red5']
        red6 = item['red6']
        blue = item['blue']
        self.fp.write(day+','+center+','+red1+','+red2+','+red3+','+red4+','+red5+','+red6+','+blue+'\n')
        return item #传个下一个管道类接受
    def close_spider(self,spider):#关闭文件
        self.fp.close()


class MysqlPipeline: #写入MYSQL数据库
    conn = None
    cou = None 
    def open_spider(self,spider):
        self.conn = pymysql.Connect(host='127.0.0.1', port=3306, user='xxx', password='xxx', db='spider', charset='utf8') #定义连接对象
        print(self.conn)

    def process_item(self, item, spider):
        day = item['day']
        center = item['center']
        red1 = item['red1']
        red2 = item['red2']
        red3 = item['red3']
        red4 = item['red4']
        red5 = item['red5']
        red6 = item['red6']
        blue = item['blue']
        #执行的mysql语句 向数据表里面插入数据
        sql = 'insert into 彩票 values("%s","%s","%s","%s","%s","%s","%s","%s","%s")'%(day, center, red1, red2, red3, red4, red5, red6, blue)
        self.cou = self.conn.cursor() #定义游标对象
        try: #事故处理 没有错误就直接提交,插入不成功就回滚到开始的位置
            self.cou.execute(sql)
            self.conn.commit()
        except Exception as e:
            print(e)
            self.conn.rollback()

        return item  #传个下一个管道类接受
    def close_spider(self,spider): #关闭连接和游标
        self.cou.close()
        self.conn.close()

第五步:在设置文件中关闭robots协议,定义日志,开启管道类,简单的UA伪装
点开 setings.py

  1. 简单的ua伪装
# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'
  1. 关闭rebots协议,定义日志类型
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
LOG_LEVEL = 'ERROR' #只输出错误的日志
  1. 开启管道
ITEM_PIPELINES = {
   'caipiaopa.pipelines.CaipiaopaPipeline': 300, #300,301数字代表优先级,越小优先集越高
   'caipiaopa.pipelines.MysqlPipeline': 301,
}

第六步:再次打开终端,进入到项目目录中输入 > scrapy crawl spider capa 回车就ok了

这里数据就采集完了。
本地数据部分截图
在这里插入图片描述
这是数据库里部分截图
在这里插入图片描述
因为scrapy是基于异步爬取的所以日期都是乱的 MySQL可以按照期号顺序查询
select * from 彩票 order by 期号 ;
这样数据就是按照顺序排好的。
当然本地文件也可以导入到pandas进行排序。。

最后简单的分析下数据

import pandas as pd   #数据处理和分析,清洗
#引入数据                            处理表头       处理行索引
df = pd.read_csv('2000期彩票.csv', header=None, index_col=0)

# 把红球号码拿出来  行:所有行都要   列:从1到6
red_boll = df.loc[:, 2:7]#用逗号分隔 先拿行再拿列
#把蓝球号码拿出来
blue_boll = df.loc[:, 8]
# #统计每个号码出现的频率             扁平化处理
red_boll_count = pd.value_counts(red_boll.values.flatten())
blue_boll_count = pd.value_counts(blue_boll)
print(red_boll_count, blue_boll_count)


红球数字出现频率
在这里插入图片描述
蓝球数字出现频率
在这里插入图片描述
感觉都差不多,所以买彩票还是靠运气!!

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页