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中相关推荐

  1. python爬取明星百度图片并存入本地文件夹

    python爬取明星百度图片并存入本地文件夹 想要一个明星图片的时候,发现图片量过大,一张张保存太累,不太现实 这时候就可以用到爬虫,批量爬取图片 现在又出现一个问题,当发现一个明星爬完后,再爬取下一 ...

  2. 【爬虫】利用Python爬虫爬取小麦苗itpub博客的所有文章的连接地址并写入Excel中(2)...

    [爬虫]利用Python爬虫爬取小麦苗itpub博客的所有文章的连接地址并写入Excel中(2) 第一篇( http://blog.itpub.net/26736162/viewspace-22865 ...

  3. Python爬取起点小说并保存到本地文件夹和MongoDB数据库中

    Python爬取起点小说并保存到本地MongoDB数据库中 工具:Python3.7 + Mongo4.0 + Pycharm """ 爬取起点小说<诡秘之主> ...

  4. Scrapy爬取妹子图保存到不同目录下

    进行设置settings #启动图片管道 ITEM_PIPELINES = {'mztu.pipelines.ImagesPipelinse': 300, } #设置默认目录地址 注意下载图片的话默认 ...

  5. scrapy爬取多页面

    前言 使用scrapy的目的是方便爬虫人员通过scrapy框架编写简单的代码,提取需要爬取的网站上有用的数据,其框架底层已经对爬虫的过程做了大量的逻辑处理,而爬虫人员只需按照指定的规则使用即可,个人觉 ...

  6. scrapy爬取酒店评论数据

    scrapy爬取酒店评论数据 代码 here:GitHub:scrapy_hotel_review 采用scrapy爬取酒店评论数据. 总共有28W条记录. 做某NLP任务,需要一些hotel rev ...

  7. 经典爬虫:用Scrapy爬取百度股票

    前言 今天我们编写一个用 Scrapy 框架来爬取百度股票的代码,之前写过一篇爬取百度股票的文章(点我),代码的逻辑和这篇文章的逻辑是一样的,用到的解析器不同罢了. Scrapy 爬虫框架 Scrap ...

  8. 【爬虫】Scrapy爬取腾讯社招信息

    目标任务:爬取腾讯社招信息,需要爬取的内容为:职位名称,职位的详情链接,职位类别,招聘人数,工作地点,发布时间. 一.预备基础 1.Scrapy简介 Scrapy是用纯Python实现一个为了爬取网站 ...

  9. Scrapy爬取姓名大全,看看那个名字最受父母青睐

    点击上方"AI搞事情"关注我们 最近在做的项目需要用到名字的数据,可哪儿有这么多名字给我用呢?经一通搜索,不仅找到一个神奇的网站姓名大全,还有人开源了爬虫的代码.让我一番修改,得到 ...

  10. 四十一、完成scrapy爬取官方网站新房的数据

    @Author:Runsen 文章目录 前言 分析网页 新建项目 加请求头 搞定item 首页调试 详情页调试 保存json 前言 在前几天,接到一个大学生的作业的爬虫单子,要求采用scrapy爬取链 ...

最新文章

  1. 开源sk-dist,超参数调优仅需3.4秒,sk-learn训练速度提升100倍
  2. Unity中对象池的使用
  3. 阿里P7工作总结:Spring MVC的工作原理,看完受益匪浅
  4. 单例模式和多例模式的区别(转)
  5. 亿级别记录的mongodb分页查询java代码实现
  6. Spring AOP编程-aspectJ代理方式选择
  7. 程序员怎么面试求职?需要注意哪些因素?
  8. Quartz框架中的Scheduler
  9. 安卓学习笔记05:Activity概述
  10. sql server 安装时提示要重启
  11. 工作失误:没有分析进程消耗了这么多内存的原因
  12. C语言 同构数的算法
  13. 一个高仿追书神器的vue阅读器。已成功做成app
  14. gcj编译java_用GCJ编译Java源文件成脱离JRE的exe可执行文件
  15. LeCo-142. 环形链表 II
  16. 易语言文本比较特征码
  17. 努力是为了让自己不平庸
  18. 2021年茶艺师(初级)考试题及茶艺师(初级)新版试题
  19. Java编程基础19——Map集合斗地主案例
  20. 2017年深圳初中终极排名(四大、八大、十大、公办率)

热门文章

  1. LG手机无法连接adb
  2. STM32解码EM4100的曼彻斯特编码(库函数版本)
  3. 俞军老师:适合产品经理的10本书 | 2019收藏版
  4. mx250显卡天梯图_mx250显卡天梯图_2020年最新笔记本显卡天梯图,看看你的显卡排在哪!...
  5. 移动电商平台弹性架构案例
  6. IMU噪声参数辨识-艾伦方差
  7. threejs给gltf模型贴图出现纹理错乱,贴图歪曲解决办法
  8. 修复 VM Player 断网问题 20121215T1402
  9. awz3格式转epub格式转mobi格式
  10. 学生id号码是什么意思_ID是什么意思?