本文仅供学习,需要数据的文末有链接下载,请不要重复爬取。

最近工作中,因为统计用区划代码和城乡划分代码更新了最新的2017版,需要爬取最新的数据。于是乎,本次花了一定精力,将整个2017版数据完完整整的爬了下来。相较于第一次爬虫练习的2016版,本次改进很多,主要特点如下。

1、通过尝试爬取目标网址,发现相较于以往,竟然设置了反爬虫手段,在进行get请求的时候需要增加headers,模拟浏览器。

2、创建headers列表,使用随机headers进行访问,反反爬虫,降低被反的可能性。

3、采用断点续尝试请求的方式提高爬虫成功率。这一点很关键,不知道是目标网址的服务器不好还是反爬虫机制,经常会出现爬取某个次级网址的时候卡住,导致请求失败。

4、使用了多进程技术,多个省份同时进行爬取,大大提高了效率。一开始使用的是单进程爬虫,有上万或数十万个网页需要爬取,发现爬完估计要一天。

5、另外发现一个小问题,观察网页返回结果,显示网页是采用gb2312的方式编码的,但实际上如果获取网址采用gb2312的话,一些生僻的汉字会乱码,采用gbk就不会出现这样的问题。

废话不多说,上代码。代码分成三部分,调度器、爬虫、下载器。

调度器:Scheduler,创建目标网址列表,开辟进程池,并统一调度爬虫脚本与下载器。

import Spiders
import downloading
from multiprocessing import Pool# 目标列表
aimurl="http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2017/"
aimurllist = ["11", "12", "13", "14", "15", "21", "22", "23", "31", "32", "33", "34", "35", "36", "37","41", "42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63", "64", "65"]def run_proc(url, num):print(num+' is running')(city, county, town, village) = Spiders.spider(url, num)downloading.download(city, county, town, village, num)print(num+' ended')if __name__ == "__main__":p = Pool(8)for i in aimurllist:p.apply_async(run_proc, args=(aimurl, i))print('Waiting for all subprocesses done ...')p.close()  # 关闭进程池p.join()  # 等待开辟的所有进程执行完后,主进程才继续往下执行print('All subprocesses done')

爬虫:spiders,主要就是写爬取网页的逻辑。通过创建headers列表,使用随机headers和采用断点续尝试请求的方式,提高成功率。另外,因为本次爬虫的深度较深,代码逻辑上是要好好思考的。感兴趣的详细看一下代码,应该可以理解爬取过程。

import requests
from bs4 import BeautifulSoup
import random
import time# 选择随机headers,降低被反爬虫的可能性
ua_list = ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv2.0.1) Gecko/20100101 Firefox/4.0.1","Mozilla/5.0 (Windows NT 6.1; rv2.0.1) Gecko/20100101 Firefox/4.0.1","Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11","Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1","Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6","Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6","Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5","Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3","Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3","Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3","Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3","Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24","Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]# 采用断点续尝试请求的方式提高爬虫成功率 经过测试网络正常一般最多retry一次就能获得结果
def getsoup(url, num_retries = 6):user_agent = random.choice(ua_list)headers = {"User-Agent": user_agent}try:res = requests.get(url,headers=headers,timeout=10) #以get方法访问目标网址获取网页信息res.encoding = 'gbk'  # 该网页是以gbk的编码形式显示的soup = BeautifulSoup(res.text, 'html.parser')  # 使用美丽汤解析网页内容return soupexcept Exception as e:if num_retries >0:time.sleep(10)print(url)print('requests fail,retry the last th' + str(num_retries) + '  ' + time.ctime())return getsoup(url, num_retries-1)else:print("retry fail!")print("error: %s" % e + "   " + url)return #返回空值 程序运行报错停止# 获取市级代码
def getsecond(url, num):city = {}soup = getsoup(url+num+'.html')for j in soup.select('.citytr '):# print(j)id = str(j.select('td')[0].text)#130100000000city[id[0:4]] = {'qhdm': id, 'name': j.select('td')[1].text, 'cxfldm': '0'}return city# 获取区县级代码
def getthird(url, lists):county = {}for i in lists:soup = getsoup(url+i[0:2]+'/'+i+'.html')for j in soup.select('.countytr '):# print(j)id = str(j.select('td')[0].text)#130201000000county[id[0:6]] = {'qhdm': id, 'name': j.select('td')[1].text, 'cxfldm': '0'}return county# 获取镇级代码 市辖区没有下级代码
def getfourth(url, lists):town = {}for i in lists:# print(url+i[0:2]+'/'+i[2:4]+'/'+i+'.html')soup = getsoup(url+i[0:2]+'/'+i[2:4]+'/'+i+'.html')for j in soup.select('.towntr '):# print(j)id = str(j.select('td')[0].text)  # 130202001000town[id[0:9]] = {'qhdm': id, 'name': j.select('td')[1].text, 'cxfldm': '0'}# 130202001return town# 获取村级代码
def getfifth(url,lists):village = {}for i in lists:# print(url+i[0:2]+'/'+i[2:4]+'/'+i[4:6]+'/'+i+'.html')soup = getsoup(url+i[0:2]+'/'+i[2:4]+'/'+i[4:6]+'/'+i+'.html')for j in soup.select('.villagetr '):# print(j)id = str(j.select('td')[0].text)  # 110101001001village[id[0:12]] = {'qhdm': id, 'name': j.select('td')[2].text, 'cxfldm': j.select('td')[1].text}# 110101001001return villagedef spider(aimurl, num):city = getsecond(aimurl, num)print(num + ' city finished!')county = getthird(aimurl, city)print(num + ' county finished!')town = getfourth(aimurl, county)print(num + ' town finished!')village = getfifth(aimurl, town)print(num + ' village finished!')print(num + " crawl finished!Now,writing into txt...")return city, county, town, village

细心的同学可以发现,怎么没有定义getfirst函数,实际上是有的,单进程脚本中是存在的。在单进程脚本中的思想是,先将全部的省级直辖市级爬取到,再将全部的市级爬取到,依此类推至村级。而在多进程脚本中,是先按照省为单位进行划分,再在每个省中依序爬取的。

下载器:downloading,就是将爬取的内容下载下来,写进文本里。

def download(city, county, town, village, num):path = r'E:\tjyqhdmhcxhfdm2017\tjyqhdmhcxhfdm2017_ ' + num + '.txt'dic = {**city, **county, **town, **village}#字典合并for i in dic.values():with open(path, 'a', encoding='utf-8') as f:f.write('"'+i['qhdm']+'","'+i['name']+'","'+i['cxfldm']+'"'+'\n')print(num+" write finished!")

完整的代码如上,感兴趣的可以复制下来尝试运行。注意:

1、请先在下载器中定义好下载地址,提前创建好文件夹。

2、在执行代码爬取一遍后,很有可能文件数没有31个,那是因为在爬取过程中,就算有断点续请求的方式,仍然会有一定可能性没有成功获取导致某个省的数据爬取失败。此时只要查看运行时监视器的输出结果,搜索error,即可定位到具体哪个省没有爬取成功。通过更改调度器中aimurllist,再次爬取即可。所以如果采用单进程的方式,几乎不可能完整的将整个数据下载下来。

最后,附上全部2017年统计用区划代码和城乡划分代码(截止2017年10月31日)数据,链接如下。

链接: https://pan.baidu.com/s/1zbQyKx1zyh4oSmi-j_WIOQ 密码: bfcu

Python爬虫练习五:爬取 2017年统计用区划代码和城乡划分代码(附代码与全部数据)相关推荐

  1. 【Python爬虫】从零开始爬取Sci-Hub上的论文(串行爬取)

    [Python爬虫]从零开始爬取Sci-Hub上的论文(串行爬取) 维护日志 项目简介 步骤与实践 STEP1 获取目标内容的列表 STEP2 利用开发者工具进行网页调研 2.1 提取文章链接和分页链 ...

  2. Python爬虫实战之爬取糗事百科段子

    Python爬虫实战之爬取糗事百科段子 完整代码地址:Python爬虫实战之爬取糗事百科段子 程序代码详解: Spider1-qiushibaike.py:爬取糗事百科的8小时最新页的段子.包含的信息 ...

  3. python爬虫 requests+bs4爬取猫眼电影 傻瓜版教程

    python爬虫 requests+bs4爬取猫眼电影 傻瓜版教程 前言 一丶整体思路 二丶遇到的问题 三丶分析URL 四丶解析页面 五丶写入文件 六丶完整代码 七丶最后 前言 大家好我是墨绿 头顶总 ...

  4. python爬虫——Cookie登录爬取豆瓣短评和影评及常见问题

    python爬虫--Cookie登录爬取豆瓣短评和影评 常见问题(本文已解决) 具体步骤 一.获取网页源码 短评.影评 二.解析网页源码及爬取评论 1.短评网页解析 ①确定位置 2.短评爬取 ①名称爬 ...

  5. python 爬虫实例 电影-Python爬虫教程-17-ajax爬取实例(豆瓣电影)

    Python爬虫教程-17-ajax爬取实例(豆瓣电影) ajax: 简单的说,就是一段js代码,通过这段代码,可以让页面发送异步的请求,或者向服务器发送一个东西,即和服务器进行交互 对于ajax: ...

  6. Python爬虫系列之爬取微信公众号新闻数据

    Python爬虫系列之爬取微信公众号新闻数据 小程序爬虫接单.app爬虫接单.网页爬虫接单.接口定制.网站开发.小程序开发 > 点击这里联系我们 < 微信请扫描下方二维码 代码仅供学习交流 ...

  7. 携程ajax,Python爬虫实战之爬取携程评论

    一.分析数据源 这里的数据源是指html网页?还是Aajx异步.对于爬虫初学者来说,可能不知道怎么判断,这里辰哥也手把手过一遍. 提示:以下操作均不需要登录(当然登录也可以) 咱们先在浏览器里面搜索携 ...

  8. Python爬虫学习笔记 -- 爬取糗事百科

    Python爬虫学习笔记 -- 爬取糗事百科 代码存放地址: https://github.com/xyls2011/python/tree/master/qiushibaike 爬取网址:https ...

  9. Python爬虫系列之爬取某奢侈品小程序店铺商品数据

    Python爬虫系列之爬取某奢侈品小程序店铺商品数据 小程序爬虫接单.app爬虫接单.网页爬虫接单.接口定制.网站开发.小程序开发> 点击这里联系我们 < 微信请扫描下方二维码 代码仅供学 ...

最新文章

  1. php for等边三角形,利用js实现等腰三角形
  2. Jquery系列:checkbox 获取值、选中、设置值、事件监听等操作
  3. SQL SERVER 2008 SN
  4. 使用Docker-镜像命令练习
  5. RMI原理揭秘之远程方法调用
  6. c语言错误re,c语言malloc之后再realloc的有关问题
  7. 山师计算机专业研究生怎么样,山东师范大学有计算机专业硕士吗?
  8. bigdecimal 保留两位小数_一起聊聊小数的储存和运算
  9. 《Spring 3.0就这么简单》——1.5 业务层
  10. hadoop,spark的启动及DataNode无法启动的解决方法
  11. latex 调整表格的行高_latex 表格如何控制行高,行距,行与行之间的距离
  12. mysql查询IP地址
  13. 一、OpenAI ChatGPT 注册使用
  14. Linux进程管理、防火墙
  15. 安全浏览器无法安装?看这一篇就够了
  16. 欧拉角,万向节锁和四元数
  17. matlab 画图添加图例时,改变图例中字体大小
  18. 每日3词 2021-03-11 【name】【attribute】【value】
  19. 关于Xylon这个名字
  20. PyTorch搭建预训练AlexNet、DenseNet、ResNet、VGG实现猫狗图片分类

热门文章

  1. 单例模式及其线程安全问题
  2. Linux系统第13章网络管理实战1
  3. 强烈推荐,分享一些让人拍案叫绝的黑科技软件(网站)
  4. Web前端开发技术实验与实践(第3版)储久良编著实训12
  5. 因易用性导致的TongWeb使用误区
  6. Win下基于通用C运行库UCRT的部署 - 及 {C++/CLI封装的托管dll被C#工程调用时出现未加载(could not load file or assembly)错误排查}
  7. springboot高校专业实习管理系统的设计和开发
  8. GSEA | 基因富集分析
  9. Free Pascal IDE安装
  10. Amazon EKS 上有状态服务启用存储加密