# coding=utf-8
# Creeper
import os
import bs4
import time
import MySQLdb
import urllib2
import datetime
import warnings
import traceback
import ConfigParser try:
basedir = os.path.dirname(os.path.abspath(__file__))
except NameError:
import sys
basedir = os.path.dirname(os.path.abspath(sys.argv[0])) SETTINGS_FILE = os.path.join(basedir, 'settings.ini')
GLOBAL_CONFIG = {
'server': {
'debug': False,
},
'db': {
'host': '127.0.0.1',
'port': '3306',
'user': 'root',
'password': '',
'dbname': 'test',
'table': 'group'
}
} def __config(item):
GLOBAL_CONFIG[sec][item[0]] = item[1]
try:
parser = ConfigParser.ConfigParser()
parser.readfp(open(SETTINGS_FILE))
for sec in parser.sections():
map(__config, parser.items(sec))
except:
print 'settings.ini needed'
raise N = 0 class Handle(object): def __init__(self, *args, **kwargs):
super(Handle, self).__init__()
self.db = {}
self.conn = None
self.cursor = None
self._cursor(**kwargs) def _cursor(self, **kwargs):
self.db.update(**kwargs)
host = kwargs.get('host', '127.0.0.1')
port = int(kwargs.get('port', 3306))
user = kwargs.get('user', 'root')
pwd = kwargs.get('password', '')
dbname = kwargs.get('dbname', 'test')
charset = kwargs.get('charset', 'utf8')
_conn = MySQLdb.connect(user=user, passwd=pwd,
host=host, port=port, charset=charset)
try:
_conn.select_db(dbname)
except:
sql = """CREATE DATABASE IF NOT EXISTS `%s` DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
""" % dbname
_conn.cursor().execute(sql)
_conn.select_db(dbname)
self.conn = _conn
self.cursor = _conn.cursor() def format_pk(self, pk, index):
d = {1:2, 2:4, 3:6, 4:9, 5:12}
try:
pk = int(float(pk))
except:
raise ValueError, 'the primary key must be integer or string interger'
return int(str(pk)[:d[index]])
while (pk * 1.0 / 10).is_integer():
pk = pk * 1.0 / 10
return pk < 10 and int(pk) * 10 or int(pk) def do_execute(self, pk, name, type, parent='NULL'):
global N
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S %f')
if N%100 == 0 and N != 0:
print 'Total: %s ---%s' % (N, now)
# time.sleep(5)
if not parent or parent == '':
parent = 'NULL'
sql = """INSERT INTO `%s` (`id`, `name`, `type`, `parent`) VALUES(%s, '%s', '%s', %s);
""" % (self.db['table'], pk, name, type, parent)
try:
self.cursor.execute(sql)
self.conn.commit()
print '+',
N += 1
except MySQLdb.Warning, w:
print "\nWarning:%s" % str(w)
print '#',
except MySQLdb.Error, e:
if not 'Duplicate entry' in str(e):
print "\nError:%s" % str(e)
self.debug(pk, name)
self.debug(pk, parent)
else:
print '=',
self.debug(pk, name)
except:
traceback.print_exc()
print '?', def do_executemany(self, items, params=None):
sql = """INSERT INTO `%s` (`id`, `name`, `type`, `parent`) VALUES """ % self.db['table']
sql +="(%s, %s, %s, %s)";
try:
self.cursor.executemany(sql, items)
self.conn.commit()
except MySQLdb.Error, e:
print "Error:%s" % str(e)
except:
traceback.print_exc() class Creeper(Handle): def __init__(self, *args, **kwargs):
Handle.__init__(self, *args, **kwargs)
self.init_db()
self.root_url = ''
self._type = {1:'province',2:'city',3:'county',4:'town',5:'village'} def init_db(self):
__sql = """CREATE TABLE IF NOT EXISTS `%s` (
`id` bigint(20) NOT NULL,
`name` varchar(30) NOT NULL,
`type` varchar(30) NOT NULL,
`parent` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`),
KEY `Group_12345` (`name`),
KEY `Group_67890` (`parent`),
FOREIGN KEY(parent) REFERENCES `%s` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
""" % (self.db['table'], self.db['table']) try:
self.cursor.execute(__sql)
self.cursor.execute("""CREATE TABLE IF NOT EXISTS `debug` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`badid` bigint(20) NOT NULL,
`others` varchar(256) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;""")
self.conn.commit()
except MySQLdb.Warning, w:
if not 'already exists' in str(w):
print "Warning:%s" % str(w)
except MySQLdb.Error, e:
print "Error:%s" % str(e)
traceback.print_exc()
except:
traceback.print_exc()
pass def debug(self, *args):
try:
_sql = """INSERT INTO `debug` (`badid`, `others`) VALUES(%s, '%s');
""" % (args[0], args[1])
self.cursor.execute(_sql)
self.conn.commit()
except:
traceback.print_exc()
finally:
return def __get_url(self, tup, index):
id = tup[0]
parent = tup[-1]
__url = []
for i in range(0, index, 2):
__url.append(str(id)[i: i+2])
__url.append(str(id))
return self.root_url + '/'.join(__url) + '.html' def format_tag(self, x_tag, url, index, limit=None):
if limit and index > limit: return
parent = str(url.split('/2013/')[1].split('/')[-1])[:-5]
__type = self._type[index]
__parent = not parent and 'NULL' or parent
if isinstance(x_tag, bs4.element.Tag) and x_tag.has_attr('href'):
print '.',
href = x_tag['href']
child_url = '/'.join(url.split('/')[:-1])
full_url = '/'.join([child_url, href])
__pk = self.format_pk(href.split('.html')[0].split('/')[-1], index)
__name = x_tag.text
i = (__pk, __name, __type, __parent)
self.do_execute(*i)
self.get_info(full_url, index + 1, limit)
else:
print '*',
__pk = self.format_pk(x_tag[0].text, index)
__name = x_tag[1].text
self.do_execute(__pk, __name, __type, __parent) def get_info(self, url, index, limit=None):
# 解析页面,获取目标区域的数据
# 获取单元数据,格式化为可供插入数据库的元组
try:
__html = urllib2.urlopen(url).read()
__soup = bs4.BeautifulSoup(__html, from_encoding='gbk')
__tr = __soup('tr', class_='%str' % self._type[index])
except:
try:
self.debug(0, url)
except:
traceback.print_exc()
finally:
return
__lst = []
for tr in __tr:
# 每个tr中的多个td代表多个省
if index == 1:
for td in tr('td'):
__lst.extend(td('a'))
continue # 每个tr中的多个td代表一个节点,取最后一个td中的a标签
if tr('td')[-1]('a'):
__lst.extend(tr('td')[-1]('a'))
else:
# 没有子节点的元素,单纯的通过td中的数据创建
self.format_tag([tr('td')[0], tr('td')[-1]], url, index, limit) for a in __lst:
self.format_tag(a, url, index, limit) def do_get_childs(self, index):
# 1. 查询获取当前层级节点数目
_sql = """SELECT COUNT( * ) FROM `%s` WHERE `type`='%s';
""" % (self.db['table'], self._type[index])
self.cursor.execute(_sql)
total = self.cursor.fetchone()[0] # 2. 遍历父节点,获取子节点数据
for i in range(0, total, 30):
_sql = """SELECT `id`, `parent` FROM `%s` WHERE `type` = '%s' LIMIT %s, %s;
""" % (self.db['table'], self._type[index], i, i+30)
self.cursor.execute(_sql)
id_and_parent = list(set(self.cursor.fetchall()))
for tup in id_and_parent:
url = self.__get_url(tup, index)
self.get_info(url, index+1) warnings.filterwarnings('error', category = MySQLdb.Warning)
del warnings if __name__ == '__main__':
url = "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/"
db_config = GLOBAL_CONFIG['db']
g = Creeper(**db_config)
g.root_url = url
g.init_db()
lst = g.get_info(url, index=1, limit=5)
# g.do_get_childs(3)

用Python实现的一个简单的爬取省市乡镇的行政区划信息的脚本的更多相关文章

  1. 【python爬虫】一个简单的爬取百家号文章的小爬虫

    需求 用"老龄智能"在百度百家号中搜索文章,爬取文章内容和相关信息. 观察网页 红色框框的地方可以选择资讯来源,我这里选择的是百家号,因为百家号聚合了来自多个平台的新闻报道.首先看 ...

  2. Python爬虫——使用 lxml 解析器爬取汽车之家二手车信息

    本次爬虫的目标是汽车之家的二手车销售信息,范围是全国,不过很可惜,汽车之家只显示100页信息,每页48条,也就是说最多只能够爬取4800条信息. 由于这次爬虫的主要目的是使用lxml解析器,所以在信息 ...

  3. 一个简单的爬取b站up下所有视频的所有评论信息的爬虫

    心血来潮搞了一个简单的爬虫,主要是想知道某个人的b站账号,但是你知道,b站在搜索一个用户时,如果这个用户没有投过稿,是搜不到的,,,这时就只能想方法搞到对方的mid,,就是 space.bilibil ...

  4. Python爬虫初探 - selenium+beautifulsoup4+chromedriver爬取需要登录的网页信息

    目标 之前的自动答复机器人需要从一个内部网页上获取的消息用于回复一些问题,但是没有对应的查询api,于是想到了用脚本模拟浏览器访问网站爬取内容返回给用户.详细介绍了第一次探索python爬虫的坑. 准 ...

  5. python定义的一个简单的shell函数的代码

    把写代码过程中经常用到的一些代码段做个记录,如下代码段是关于python定义的一个简单的shell函数的代码. pipe = subprocess.Popen(cmd, stdout=subproce ...

  6. Python爬虫学习三------requests+BeautifulSoup爬取简单网页

    第一次第一次用MarkDown来写博客,先试试效果吧! 昨天2018俄罗斯世界杯拉开了大幕,作为一个伪球迷,当然也得为世界杯做出一点贡献啦. 于是今天就编写了一个爬虫程序将腾讯新闻下世界杯专题的相关新 ...

  7. 使用python爬取MedSci上的期刊信息

    使用python爬取medsci上的期刊信息,通过设定条件,然后获取相应的期刊的的影响因子排名,期刊名称,英文全称和影响因子.主要过程如下: 首先,通过分析网站http://www.medsci.cn ...

  8. Python爬虫开源项目代码,爬取微信、淘宝、豆瓣、知乎、新浪微博、QQ、去哪网等 代码整理

    作者:SFLYQ 今天为大家整理了32个Python爬虫项目.整理的原因是,爬虫入门简单快速,也非常适合新入门的小伙伴培养信心.所有链接指向GitHub,祝大家玩的愉快 1.WechatSogou [ ...

  9. 零基础爬虫----python爬取豆瓣电影top250的信息(转)

    今天利用xpath写了一个小爬虫,比较适合一些爬虫新手来学习.话不多说,开始今天的正题,我会利用一个案例来介绍下xpath如何对网页进行解析的,以及如何对信息进行提取的. python环境:pytho ...

随机推荐

  1. 推荐一个可视化的学习Git的好网站:LearnGitBranching

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:推荐一个可视化的学习Git的好网站:LearnGitBranching.

  2. KVM地址翻译流程及EPT页表的建立过程

    本博文为原创,遵循CC3.0协议,转载请注明出处:http://blog.csdn.net/lux_veritas/article/details/9284635 ------------------ ...

  3. BMVC reading list

    'Combining Local and Global Cues for Closed Contour Extraction' Vida Movahedi, James Elder 'FRIF: Fa ...

  4. [置顶] Linux下的截图小工具

    Linux下的截图工具scrot 基于命令行 先下载:scrot apt-get install scrot 对该工具的操作: 分为以下几个部分 1.抓取整个桌面 scrot pic.jpg 2.抓取 ...

  5. android自定义TabWidget

    在做项目的时候,需要用到这个选项卡,刚开始看了系统的tabwidget,囧了,底边有黑线不说,还不美观,扒了好多的网页发现前辈做的能够满足自己的需求,将代码修改了下,就能用喽,伟人说过,站在前辈的肩膀 ...

  6. Linux内核源代码情景分析系列

    http://blog.sina.com.cn/s/blog_6b94d5680101vfqv.html Linux内核源代码情景分析---第五章 文件系统  5.1 概述 构成一个操作系统最重要的就 ...

  7. java定义类 对象,引用,指针

    java是根据面向对象编程,因此有类和对象的概念,类分为普通类与抽象类. 一.定义类 类由N个 构造器  成员变量  方法组成,可以不定义,也可以根据语法定义N个. [修饰符] class 类名{ 构 ...

  8. MDA系统分析实战--图书馆管理系统

    MDA系统分析实战--图书馆管理系统 本文通过MDA系统分析方法,对图书馆管理系统进行分析,简要叙述系统分析的一般过程.首先,简要介绍什么是MDA:MDA(Model-Driven Architect ...

  9. C#/.net七牛云存储上传图片(文件)操作

    七牛云存储官方: C#SDK(http://developer.qiniu.com/docs/v6/sdk/csharp-sdk.html) 注册成为标准用户就可获得:10GB永久免费存储空间/ 每月 ...

  10. 雷鸟(Thunderbird)收取Gmail出错,收到警告邮件

    如题,每次打开thunderbird都会收到以下提醒邮件,后来发现,只要将thunderbird中和google服务有关的插件卸载掉就可以了 We prevented the sign-in atte ...