實戰項目-基於國家統計局城鄉規劃數據的地名提取(1)
超簡單的小項目,涉及到簡單的爬蟲以及基礎的python編程知識。很簡單哦
最近手裏有一份公司的名單,其中大部分包含了地名信息。要求根據公司名稱,獲取到公司所屬的地級市。類似於如下。可以看到每個公司名稱都會包含一個地名信息,但其中有一部分是xx縣,xx鄉,xx區,對於這一部分信息就需要找到這個地名他所屬的上級地級市。
我最終用了一種曲線救國的辦法。首先用分詞工具將公司名稱中的地名提取出來,然後採集國家統計局地名數據,根據地名匹配到公司所屬地級市。
這裏我使用的分詞工具是jieba。結巴使用方法也很簡單,直接pip安裝就行 。
pip install jieba
拿一個公司名測試下,可以看到已經將地名完美分割出來。
// An highlighted block
import jieba
words = jieba.lcut('銅陵市建設投資控股有限責任公司')
print(words)
接下來就是獲取全國的地名數據,並保存爲json文件。這一部分我是採集了國家統計局城鄉規劃的官網。
http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2018/index.html
網站很簡潔,一個基本上沒有反爬措施的靜態頁面,使用request+xpath+json可以完美實現。
接下來簡單分析一下頁面,因爲是靜態頁面,所以直接打開F12的elements分析就行。這個網站首頁是省份的列表頁,然後點擊進入,依次是地級市-區-鎮/鄉等的列表頁。
對於省份的列表頁,可以通過xpath提取出數據
後續地級市,區,區以下地名數據採集與省份列表頁相似,就不一一贅述了。需要注意的是,最終需要保存的數據結構分爲兩種類型。
1.[{湖南省:{郴州市:{***區:[地名1, 地名2, .....], }, {}, {}....}, {}, {}, ....}, {}, {}........]
一個大列表 列表中每個元素是字典,每個字典中包含每個省份的地級市信息,每個地級市對應地級市下屬地名信息的字典,由此類推。
方便根據地名,向上匹配地級市。
2.[{湖南省:[地名1, 地名2, .....]}, {}, {},....]
一個大列表 列表中每個元素是字典,字典中每個鍵是省份,值是每個省份下所有地名信息。
方便根據地名,向上匹配省份。
在數據採集完畢後,需要保存爲本地文件。將python數據結構存儲爲實體文件,其實有兩種方式。分別是pickle,json。
在這裏我選擇json保存,
確定了保存結構之後,完善代碼如下
// An highlighted block
import requests
from lxml import etree
import time
import json
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36,',
# 'Host': 'www.stats.gov.cn',
# 'Cookie': '_trs_uv=k163tn1b_6_51kd; AD_RS_COOKIE=20080918',
}
start_url = 'http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2018/'
time.sleep(3)
rep = requests.get(start_url, headers=headers)
rep.encoding = rep.apparent_encoding
Text = rep.text
sel = etree.HTML(Text)
Province_names = sel.xpath('//*[@class="provincetr"]/td/a/text()') # 省或直轄市名稱
Province_urls = sel.xpath('//*[@class="provincetr"]/td/a/@href') # 省或直轄市url
China_place_data = {}
china_place_data = {}
for Province_name, Province_url in zip(Province_names, Province_urls):
Province_url = start_url + Province_url
rep = requests.get(Province_url, headers=headers)
time.sleep(3)
rep.encoding = rep.apparent_encoding
sel = etree.HTML(rep.text)
Province = [] # 省份下地名列表
City_names = sel.xpath('//tr[@class="citytr"]/td[2]/a/text()') # 地級市名稱
City_urls = sel.xpath('//tr[@class="citytr"]/td[2]/a/@href') # 地級市url
Province += City_names # 加入省份下地名列表
china_place_data[Province_name] = {}
for City_name, City_url in zip(City_names, City_urls):
City_url = start_url + City_url
rep = requests.get(City_url, headers=headers)
time.sleep(3)
rep.encoding = rep.apparent_encoding
sel = etree.HTML(rep.text)
County_names = sel.xpath('//tr[@class="countytr"]/td[2]/a/text()') # 區名稱
County_urls = sel.xpath('//tr[@class="countytr"]/td[2]/a/@href') # 區url
Province += County_names # 加入省份下地名列表
china_place_data[Province_name][City_name] = {}
for County_name, County_url in zip(County_names, County_urls):
County_url = Province_url.replace('.html', '/') + County_url
rep = requests.get(County_url, headers=headers)
time.sleep(3)
rep.encoding = rep.apparent_encoding
Text = rep.text
sel = etree.HTML(Text)
Town_names = sel.xpath('//tr[@class="towntr"]/td[2]/a/text()') # 鎮名稱
Town_urls = sel.xpath('//tr[@class="towntr"]/td[2]/a/@href') # 鎮url
Province += Town_names # 加入省份下地名列表
china_place_data[Province_name][City_name][County_name] = Town_names
print('{}採集完畢'.format(County_name))
print('{}採集完畢'.format(Province_name))
China_place_data[Province_name] = Province
print(China_place_data)
print(china_place_data)
China_place_data = json.dumps(China_place_data) # 轉換爲json格式
china_place_data = json.dumps(china_place_data) # 轉換爲json格式
with open('China_place_data.json', 'w') as f: # 保存爲json文件
f.write(China_place_data)
with open('china_place_data.json', 'w') as f: # 保存爲json文件
f.write(china_place_data)
其中China_place_data與china_place_data分別對應以上兩種數據結構。
每次請求之間加入了3秒休眠,做一個有素質的爬蟲。
基於國家統計局的地名提取爬蟲部分就到此結束啦。
歡迎掃碼關注: