scrapy爬取统计局的城乡代码,以目录文件夹形式生成,同时最后保存在excel中
1、创建Scrapy项目
scrapy startproject Stats
2.进入项目目录,使用命令genspider创建Spider
scrapy genspider stats stats.gov.cn
3、定义要抓取的数据(处理items.py文件)
# -*- coding: utf-8 -*-
import scrapyclass StatsItem(scrapy.Item):# 第一级名称,各个省、直辖市first_titles = scrapy.Field()# 第一级urlfirst_urls = scrapy.Field()# 第一级存储目录first_filename = scrapy.Field()# 第二级名称,市、县second_titles = scrapy.Field()# 第二级urlsecond_urls = scrapy.Field()# 第二级代码IDsecond_id = scrapy.Field()# 二级存储目录second_filename = scrapy.Field()# 第三级名称,区third_titles = scrapy.Field()# 第三级urlthird_urls = scrapy.Field()# 第三级代码IDthird_id = scrapy.Field()# 三级存储目录third_filename = scrapy.Field()# 第四级名称,办事处fourth_titles = scrapy.Field()# 第四级urlfourth_urls = scrapy.Field()# 第四级代码IDfourth_id = scrapy.Field()# 四级存储目录fourth_filename = scrapy.Field()# 第五级名称,村,居委会fifth_titles = scrapy.Field()# 第五级代码IDfifth_id = scrapy.Field()# 五级存储目录fifth_filename = scrapy.Field()
4、编写提取item数据的Spider(在spiders文件夹下:stats.py)
# -*- coding: utf-8 -*-
# 爬取统计局的城乡代码
import scrapy
import os
from Stats.items import StatsItemclass StatsSpider(scrapy.Spider):name = 'stats'allowed_domains = ['stats.gov.cn']start_urls = ['http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/index.html']# 各个省、直辖市url前缀url = 'http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/'def parse(self, response):print("处理第一级数据……")items = []# 第一级名称,各个省、直辖市(这里可以修改规则,爬取一部分省份)first_titles = response.xpath('//tr//td/a/text()').extract()# 第一级url>>>13.htmlfirst_urls_list = response.xpath('//tbody//table//tr//td//a//@href').extract()# 爬取第一级名称,各个省、直辖市for i in range(0, len(first_titles)):item = StatsItem()# 指定第一级目录的路径和目录名first_filename = "./Data/" + first_titles[i]#如果目录不存在,则创建目录if(not os.path.exists(first_filename)):os.makedirs(first_filename)item['first_filename'] = first_filename# 保存第一级名称和url,但是url需要补全item['first_titles'] = first_titles[i]# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13.htmlitem['first_urls'] = self.url + first_urls_list[i]items.append(item)# 发送第一级爬取的urlfor item in items:yield scrapy.Request(url=item['first_urls'],meta={'meta_1': item},callback= self.second_parse)# 处理第二级名称以及url,市、县def second_parse(self,response):print("处理第二级数据……")# 提取每次Response的meta数据meta_1 = response.meta['meta_1']# 提取第二级的名称、url及idsecond_titles = response.xpath('//tr//td[2]/a/text()').extract()# 第二级url>>>>13/1301.htmlsecond_urls_list = response.xpath('//tbody//table//tr//td[2]//a//@href').extract()second_id = response.xpath('//tr//td[1]/a/text()').extract()items = []for i in range(0,len(second_urls_list)):# url拼接>>>http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/1301.htmlsecond_urls = self.url + second_urls_list[i]# 第一级链接地址:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13.html# 如果属于第一级相应省、直辖市,将存储目录放在相应文件夹中,第一级的链接去掉.html才能判断是否属于#例如:修改后第一级链接http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13 和# 第二级链接http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/1301.html 这样才可以判断if_belong = second_urls.startswith(meta_1['first_urls'][:-5])if (if_belong):# 目录类似于:\Data\河北省\河北省 石家庄市second_filename = meta_1['first_filename']+"/"+ meta_1['first_titles']+" " + second_titles[i]# 如果目录不存在,则创建目录if (not os.path.exists(second_filename)):os.makedirs(second_filename)item = StatsItem()item['first_titles'] = meta_1['first_titles']item['first_urls'] = meta_1['first_urls']item['second_titles'] = meta_1['first_titles']+" " + second_titles[i]item['second_urls'] = second_urlsitem['second_id'] = second_id[i]item['second_filename'] = second_filenameitems.append(item)# 发送第二级urlfor item in items:yield scrapy.Request(url= item['second_urls'],meta={'meta_2':item},callback= self.third_parse)# 处理第三级数据名称,区def third_parse(self,response):print("处理第三级数据……")# 提取每次Response的meta数据meta_2 = response.meta['meta_2']# 提取第三级的名称、url及idthird_titles = response.xpath('//tr//td[2]/a/text()').extract()# 第三级url>>>01/130102.html http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/01/130102.htmlthird_urls_list = response.xpath('//tbody//table//tr//td[2]//a//@href').extract()third_id = response.xpath('//tr//td[1]/a/text()').extract()items = []for i in range(0,len(third_urls_list)):# url拼接>>>http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/01/130102.htmlthird_urls = self.url + meta_2['second_id'][:2] + "/" + third_urls_list[i]# 第二级链接地址:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/1301.html# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/11/1101.html# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/34/3415.html# 如果属于第二级相应市、县,将存储目录放在相应文件夹中,第二级的链接最后两位数字01是否和# 第三级链接倒数第14位至倒数第13位是否相等(或者第三级链接倒数第9位至第8位)# 或者:第二级链接最后4位(1301)和第三级链接倒数第11位至第8位是否相等# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/01/130102.html# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/11/01/110101.html# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/34/15/341502.html# if_belong = third_urls.startswith(meta_2['second_urls'][:-9])if (meta_2['second_urls'][-7:-5])==(third_urls[-14:-12]):# if (if_belong):# 目录类似于:\Data\河北省\河北省 石家庄市\河北省 石家庄市 长安区 130102000000third_filename=meta_2['second_filename']+'/'+meta_2['second_titles']+" "+third_titles[i]+" "+third_id[i]# 如果目录不存在,则创建目录if (not os.path.exists(third_filename)):os.makedirs(third_filename)item = StatsItem()item['first_titles'] = meta_2['first_titles']item['first_urls'] = meta_2['first_urls']item['second_titles'] = meta_2['second_titles']item['second_urls'] = meta_2['second_urls']item['second_id'] = meta_2['second_id']item['second_filename'] = meta_2['second_filename']item['third_titles'] = meta_2['second_titles'] + " "+third_titles[i]+" "+third_id[i]item['third_urls'] = third_urlsitem['third_id'] = third_id[i]item['third_filename'] = third_filenameitems.append(item)# 发送第三级urlfor item in items:yield scrapy.Request(url=item['third_urls'],meta={'meta_3':item},callback=self.fourth_parse)# 处理第四级数据名称,办事处def fourth_parse(self,response):print("处理第四级数据……")# 提取每次Response的meta数据meta_3 = response.meta['meta_3']# 提取第四级的名称、url及idfourth_titles = response.xpath('//tr//td[2]/a/text()').extract()# 第四级url>>>02/130102001.html http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/01/02/130102001.htmlfourth_urls_list = response.xpath('//tbody//table//tr//td[2]//a//@href').extract()fourth_id = response.xpath('//tr//td[1]/a/text()').extract()items = []for i in range(0,len(fourth_urls_list)):# url拼接>>>http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/01/02/130102001.htmlfourth_urls = self.url + meta_3['third_id'][:2] + "/" + meta_3['third_id'][2:4]+"/"+fourth_urls_list[i]# 第三级链接地址:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/01/130102.html# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/01/130104.html# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/11/01/110101.html# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/11/01/110102.html# 如果属于第三级相应区,将存储目录放在相应文件夹中,第三级链接最后两位数字02和第四级链接倒数第17位至# 倒数第16位是否相等来判断(或者第四级链接的倒数第10位至倒数第9位)# 或者第三级链接最后6位数字(130102)和第四级链接倒数第14位至倒数第9位是否相等# 第四级链接http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/01/02/130102001.html# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/13/01/04/130104001.html# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/11/01/01/110101001.html# http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/11/01/02/110102001.htmlif (meta_3['third_urls'][-7:-5]) == fourth_urls[-17:-15]:# 最后一级目录不应该出现上一级目录结尾的数字和最后一个空格,即: 130102000000,要切掉# 目录类似于:\Data\河北省\河北省 石家庄市\河北省 石家庄市 长安区 130102000000\河北省 石家庄市 长安区 建北街道办事处 130102001000m = meta_3['third_titles']fourth_filename=meta_3['third_filename']+'/'+m[:m.rfind(" ")]+" "+fourth_titles[i]+" "+fourth_id[i]# 如果目录不存在,则创建if (not os.path.exists(fourth_filename)):os.makedirs(fourth_filename)item = StatsItem()item['first_titles'] = meta_3['first_titles']item['first_urls'] = meta_3['first_urls']item['second_titles'] = meta_3['second_titles']item['second_urls'] = meta_3['second_urls']item['second_id'] = meta_3['second_id']item['second_filename'] = meta_3['second_filename']item['third_titles'] = meta_3['third_titles']item['third_urls'] = meta_3['third_urls']item['third_id'] = meta_3['third_id']item['third_filename'] = meta_3['third_filename']item['fourth_titles'] = m[:m.rfind(" ")]+" "+fourth_titles[i]+" "+fourth_id[i]item['fourth_urls'] = fourth_urlsitem['fourth_id'] = fourth_id[i]item['fourth_filename'] = fourth_filenameitems.append(item)# 发送第四级urlfor item in items:yield scrapy.Request(url=item['fourth_urls'],meta={"meta_4":item},callback=self.fifth_parse)# 处理第五级数据名称,村、居委会def fifth_parse(self,response):print("处理第五级数据……")#提取每次Response的meta数据meta_4 = response.meta['meta_4']# 提取第五级的名称及idfifth_titles = response.xpath('//tr[@class="villagetr"]//td[3]/text()').extract()fifth_id = response.xpath('//tr[@class="villagetr"]//td[1]/text()').extract()items = []for i in range(0, len(fifth_titles)):# 因为最后一级没有url链接,所以可以判断本页的url地址和上次传的url地址是否一样if (response.url == meta_4['fourth_urls']):# 目录类似于:\Data\河北省\河北省 石家庄市\河北省 石家庄市 长安区 130102000000\河北省 石家庄市 长安区 建北街道办事处 130102001000\# 河北省 石家庄市 长安区 建北街道办事处 棉一社区居民委员会 130102001001# # 最后一级目录不应该出现上一级目录结尾的数字和最后一个空格,即: 130102001000,要切掉m = meta_4['fourth_titles']fifth_filename = meta_4['fourth_filename']+"/"+m[:m.rfind(" ")]+" "+fifth_titles[i]+" "+fifth_id[i]if (not os.path.exists(fifth_filename)):os.makedirs(fifth_filename)item = StatsItem()# item['first_titles'] = meta_4['first_titles']# item['first_urls'] = meta_4['first_urls']# item['second_titles'] = meta_4['second_titles']# item['second_urls'] = meta_4['second_urls']# item['second_id'] = meta_4['second_id']# item['second_filename'] = meta_4['second_filename']item['third_titles'] = meta_4['third_titles']# item['third_urls'] = meta_4['third_urls']item['third_id'] = meta_4['third_id']# item['third_filename'] = meta_4['third_filename']item['fourth_titles'] = meta_4['fourth_titles']# item['fourth_urls'] = meta_4['fourth_urls']item['fourth_id'] = meta_4['fourth_id']# item['fourth_filename'] = meta_4['fourth_filename']# item['fifth_filename'] = fifth_filenameitem['fifth_id'] = fifth_id[i]# 河北省 石家庄市 长安区 建北街道办事处 棉一社区居民委员会 130102001001item['fifth_titles'] = m[:m.rfind(" ")]+" "+fifth_titles[i]+" "+fifth_id[i]items.append(item)yield item
5.处理pipelines管道文件保存数据,可将结果保存到文件中(pipelines.py)
# -*- coding: utf-8 -*-
import json
from openpyxl import Workbook# 转码操作,继承json.JSONEncoder的子类
class MyEncoder(json.JSONEncoder):def default(self, o):if isinstance(o, bytes):return str(o, encoding='utf-8')return json.JSONEncoder.default(self, o)
# 处理数据,将数据保存在本地的excel表中
class StatsPipeline(object):def __init__(self):# self.filename = open("stats.csv", "w", encoding="utf-8")self.wb = Workbook()self.ws = self.wb.active# 创建表头self.ws.append(['third_titles','third_id','fourth_titles','fourth_id','fifth_titles','fifth_id'])def process_item(self, item, spider):# text = json.dumps((dict(item)), ensure_ascii=False, cls=MyEncoder) + '\n'# self.filename.write(text)# 只取六项,可以结合情况修改,保存到excel表中text = [item['third_titles'],item['third_id'],item['fourth_titles'],item['fourth_id'],item['fifth_titles'],item['fifth_id']]self.ws.append(text)return itemdef close_spider(self, spider):self.wb.save('stats.xlsx')print("数据处理完毕,谢谢使用!")
6.配置settings文件(settings.py)
# Obey robots.txt rules,具体含义参照:https://blog.csdn.net/z564359805/article/details/80691677
ROBOTSTXT_OBEY = False # Override the default request headers:添加User-Agent信息
DEFAULT_REQUEST_HEADERS = { 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0);', # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', # 'Accept-Language': 'en',
} # Configure item pipelines去掉下面注释,打开管道文件
ITEM_PIPELINES = { 'Stats.pipelines.StatsPipeline': 300,
} # 还可以将日志存到本地文件中(可选添加设置)
LOG_FILE = "stats.log"
LOG_LEVEL = "DEBUG"
# 包含打印信息也一起写进日志里
LOG_STDOUT = True
7.以上设置完毕,进行爬取:执行项目命令crawl,启动Spider:
scrapy crawl stats
效果图:
scrapy爬取统计局的城乡代码,以目录文件夹形式生成,同时最后保存在excel中相关推荐
- python爬取明星百度图片并存入本地文件夹
python爬取明星百度图片并存入本地文件夹 想要一个明星图片的时候,发现图片量过大,一张张保存太累,不太现实 这时候就可以用到爬虫,批量爬取图片 现在又出现一个问题,当发现一个明星爬完后,再爬取下一 ...
- 【爬虫】利用Python爬虫爬取小麦苗itpub博客的所有文章的连接地址并写入Excel中(2)...
[爬虫]利用Python爬虫爬取小麦苗itpub博客的所有文章的连接地址并写入Excel中(2) 第一篇( http://blog.itpub.net/26736162/viewspace-22865 ...
- Python爬取起点小说并保存到本地文件夹和MongoDB数据库中
Python爬取起点小说并保存到本地MongoDB数据库中 工具:Python3.7 + Mongo4.0 + Pycharm """ 爬取起点小说<诡秘之主> ...
- Scrapy爬取妹子图保存到不同目录下
进行设置settings #启动图片管道 ITEM_PIPELINES = {'mztu.pipelines.ImagesPipelinse': 300, } #设置默认目录地址 注意下载图片的话默认 ...
- scrapy爬取多页面
前言 使用scrapy的目的是方便爬虫人员通过scrapy框架编写简单的代码,提取需要爬取的网站上有用的数据,其框架底层已经对爬虫的过程做了大量的逻辑处理,而爬虫人员只需按照指定的规则使用即可,个人觉 ...
- scrapy爬取酒店评论数据
scrapy爬取酒店评论数据 代码 here:GitHub:scrapy_hotel_review 采用scrapy爬取酒店评论数据. 总共有28W条记录. 做某NLP任务,需要一些hotel rev ...
- 经典爬虫:用Scrapy爬取百度股票
前言 今天我们编写一个用 Scrapy 框架来爬取百度股票的代码,之前写过一篇爬取百度股票的文章(点我),代码的逻辑和这篇文章的逻辑是一样的,用到的解析器不同罢了. Scrapy 爬虫框架 Scrap ...
- 【爬虫】Scrapy爬取腾讯社招信息
目标任务:爬取腾讯社招信息,需要爬取的内容为:职位名称,职位的详情链接,职位类别,招聘人数,工作地点,发布时间. 一.预备基础 1.Scrapy简介 Scrapy是用纯Python实现一个为了爬取网站 ...
- Scrapy爬取姓名大全,看看那个名字最受父母青睐
点击上方"AI搞事情"关注我们 最近在做的项目需要用到名字的数据,可哪儿有这么多名字给我用呢?经一通搜索,不仅找到一个神奇的网站姓名大全,还有人开源了爬虫的代码.让我一番修改,得到 ...
- 四十一、完成scrapy爬取官方网站新房的数据
@Author:Runsen 文章目录 前言 分析网页 新建项目 加请求头 搞定item 首页调试 详情页调试 保存json 前言 在前几天,接到一个大学生的作业的爬虫单子,要求采用scrapy爬取链 ...
最新文章
- 开源sk-dist,超参数调优仅需3.4秒,sk-learn训练速度提升100倍
- Unity中对象池的使用
- 阿里P7工作总结:Spring MVC的工作原理,看完受益匪浅
- 单例模式和多例模式的区别(转)
- 亿级别记录的mongodb分页查询java代码实现
- Spring AOP编程-aspectJ代理方式选择
- 程序员怎么面试求职?需要注意哪些因素?
- Quartz框架中的Scheduler
- 安卓学习笔记05:Activity概述
- sql server 安装时提示要重启
- 工作失误:没有分析进程消耗了这么多内存的原因
- C语言 同构数的算法
- 一个高仿追书神器的vue阅读器。已成功做成app
- gcj编译java_用GCJ编译Java源文件成脱离JRE的exe可执行文件
- LeCo-142. 环形链表 II
- 易语言文本比较特征码
- 努力是为了让自己不平庸
- 2021年茶艺师(初级)考试题及茶艺师(初级)新版试题
- Java编程基础19——Map集合斗地主案例
- 2017年深圳初中终极排名(四大、八大、十大、公办率)