版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010815486/article/details/83786152
接着上一篇文章,我们已经可以用爬虫访问目标网站爬取页面了,现在需要自动提交表单查询数据,并且从页面中筛选出每期中奖号码保存为json文件导出。首先创建一个scrapy.Item类(打开项目文件夹下的items.py文件):
import scrapy
class SsqSpiderItem(scrapy.Item):
issue_num = scrapy.Field()
red = scrapy.Field()
blue = scrapy.Field()
我们需要爬取每期中奖号码的期数,以及红球数组和蓝球号;定义属性值为scrapy.Field()。然后回到爬虫代码引入这个类:
from ssq_spider.items import SsqSpiderItem
直接贴一个写好的代码:
# -*- coding: utf-8 -*-
import scrapy
from scrapy.http import Request, FormRequest
from ssq_spider.items import SsqSpiderItem
class SsqSpider(scrapy.Spider):
name = 'ssq'
allowed_domains = ['http://zst.aicai.com/ssq/'] # 爬取域名
# start_urls = ['http://zst.aicai.com/ssq/']
# 爬取网址,只适于不需要提交cookie的网站,因为没法设置cookie等信息
scope_date = [['2012001', '2014200'], [
'2015001', '2017200'], ['2018001', '2018130']]
# 设置浏览器用户代理
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0'}
def start_requests(self):
# 第一次请求页面,设置开启cookie使其得到cookie,设置回调函数
return [Request('http://zst.aicai.com/ssq/', meta={'cookiejar': 1}, callback=self.parse)]
def parse(self, response):
print('请求头信息')
print(response.request.headers)
print('响应头信息')
print(response.headers)
print(response.status)
print('---Cookie---')
# 请求Cookie
request_Cookie = response.request.headers.getlist('Cookie')
print(request_Cookie)
# 响应Cookie
response_Cookie = response.headers.getlist('Set-Cookie')
print(response_Cookie)
print('---end---')
# 设置提交表单信息,对应抓包得到字段
for i in SsqSpider.scope_date:
form_data = {
'startIssue': i[0],
'endIssue': i[1],
'sIssue': '',
'eIssue': '',
'maxsize': '30',
'openDate': '',
'statisticsTag': '1',
'sortTag': 'up'
}
# 第二次用表单post请求,携带Cookie、浏览器代理等信息给Cookie授权
yield FormRequest.from_response(response,
url='http://zst.aicai.com/ssq/', # 真实post地址
meta={'cookiejar': response.meta[
'cookiejar']},
headers=self.header,
formdata=form_data,
callback=self.next,
dont_filter=True
)
def next(self, response):
items = SsqSpiderItem()
print(response.css('title').extract())
html_tr = response.css('#tdata tr:not(.tdbck)')
for i in html_tr:
items['issue_num'] = i.css('td:nth-child(1)::text').extract()[0]
items['red'] = i.css('.chartBall01::text').extract()
items['blue'] = i.css('.chartBall02::text').extract()[0]
yield items
从response对象中用scrapy自带的css选择器解析提取出数据,运行命令就可以导出json文件:
scrapy crawl '爬虫名称' -o items.json
或者通过配置pipelines导出json文件,打开pipelines.py:
import codecs
import os
import json
class JsonPipeline(object):
def process_item(self, item, spider):
base_dir = os.getcwd()
filename = base_dir + '/ssq_item.json'
# 打开json文件,以dumps的方式将一个Python数据类型列表进行json格式的编码
# 注意需要有一个参数ensure_ascii=False ,不然数据会直接为utf编码的方式存入
with codecs.open(filename, 'a') as f:
line = json.dumps(dict(item), ensure_ascii=False) + ',\n'
f.write(line)
return item
接着编写settings.py ,我们需要在Settings.py将我们写好的pipeline添加进去,这里只需要增加一个dict格式ITEM_PIPELINES,数字value可以自定义,数字越小的优先处理。
ITEM_PIPELINES = {
'ssq_spider.pipelines.JsonPipeline': 300,
}
运行爬虫就能导出json:
scrapy crawl '爬虫名称'
需要注意的是,这样导出的json文件格式不太严谨(缺少[ ]字符,程序直接读取json文件会报错);由于scrapy框架为了运行更有效率,采用的是多线程并行爬取,所以爬取的数据没有顺序:
强迫症表示不能忍,新建一个python文件用来排序:
import json
def sorting_json():
with open('./spiders/ssq_item.json', 'r', encoding='utf-8') as s_i:
json_data = json.load(s_i, strict=False)
# 利用issue_num字段排序
json_data.sort(key=lambda x: x['issue_num'], reverse=True)
return json_data
with open('ssq.js', 'a') as s:
n = sorting_json()
for i, value in enumerate(n):
if i == 0:
s.write('var ssq_data = [')
line = json.dumps(dict(value), ensure_ascii=False) + ',\n'
if i == len(n) - 1:
line = json.dumps(dict(value), ensure_ascii=False) + ']'
s.write(line)
有了数据,就可以为所欲为了(邪魅一笑~):
随便用js写了个代码,想看看从2012年到现在有没有2期6个红球完全相同的情况,可惜没有;5个红球相同倒是有,而且13年有相邻的两期5个红球和蓝球号都一样。(被安排的明明白白……)
感慨一下,写爬虫其实不难,难的是反爬处理,这里推荐一个链接:https://weibo.com/ttarticle/p/show?id=2309404125351516226870