數據庫設計
數據庫省份表(province)
城市表(city)
Python代碼
import requests
from lxml import etree
import pymysql
from fake_useragent import UserAgent
#請求方法
def request(param):
url = 'http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2018/'
url = url + param
# 僞裝
ua = UserAgent()
headers = {'User-Agent':ua.random}
response = requests.get(url=url,headers=headers)
# 獲取字符集編碼
response.encoding = response.apparent_encoding
data = response.text
# 將源碼數據加載到數據對象中
data = etree.HTML(data)
return data
param = 'index.html'
data = request(param)
#省份數據列表
province_data = []
#城市數據列表
city_data = []
province_list = data.xpath('//tr[@class="provincetr"]/td')
for provinceli in province_list:
province = provinceli.xpath('./a/text()')[0]
#獲取省份下一級鏈接
next_src =provinceli.xpath('./a/@href')[0]
#獲取省份id值,爲城市表的外鍵
province_id = next_src.split('.')[0]
print('-----------' + province + '爬取成功,進入城市爬取-----------')
#對省份數據進行切片、數據轉換處理
# 思路
# 1、先創建一個空的列表
# 2、根據省份表的需要,將省份id、名字添加到空的列表中
# 3、將添加過後的列表轉化爲元組
# 4、將轉換後的元祖添加到全局列表中(列表名稱爲:級別 + _data)
pro_data = []
pro_data.append(province_id)
pro_data.append(province)
pro_data = tuple(pro_data)
province_data.append(pro_data)
#進入城市查詢
data = request(next_src)
city_list = data.xpath('//tr[@class="citytr"]')
for cityli in city_list:
city_name = cityli.xpath('./td[2]/a/text()')[0]
# 獲取城市下一級鏈接
city_next_src = cityli.xpath('./td[1]/a/@href')[0]
# 獲取城市id
city_id = cityli.xpath('./td[1]/a/text()')[0]
print(city_name + city_next_src + city_id + ' 爬取成功!!')
# 對城市數據進行切片、數據轉換處理
# 思路
# 1、先創建一個空的列表
# 2、根據城市表的需要,將城市id、名字、上一級省份ID(省份,城市這兩個頁面比較特殊)添加到空的列表中
# 3、將添加過後的列表轉化爲元組
# 4、將轉換後的元祖添加到全局列表中(列表名稱爲:級別 + _data)
#---cit_data 的名字要與全局city_data區分開,起名有點相似 cit_data != city_data
cit_data = []
up_id = city_next_src.split('/')[0] #城市表上一級id(外鍵)
new_src = city_next_src.split('/')[1] #城市下一級
cit_data.append(city_id)
cit_data.append(city_name)
cit_data.append(up_id)
# print(cit_data)
cit_data = tuple(cit_data)
city_data.append(cit_data)
print(province_data)
#連接數據庫
connecion =pymysql.connect (
host='localhost', # 數據庫地址
user='root', # 數據庫用戶名
password='19981216', # 數據庫密碼
db='china', # 數據庫名稱
)
cursor = connecion.cursor()
province_sql = 'insert into province(province_id,province_name) values (%s,%s)'
city_sql = 'insert into city(city_id,city_name,up_id) values (%s,%s,%s)'
cursor.executemany(province_sql,province_data)
connecion.commit()
print(cursor.rowcount)
cursor.executemany(city_sql,city_data)
connecion.commit()
print(cursor.rowcount)
cursor.close()
connecion.close()
總結:
- 利用xpath解析的時候,一定要把路徑寫正確。一直以爲省份和城市的數據解析路徑一樣,然後就一直解析不出來
- 使用了fake_useragent瀏覽器僞裝庫,但是因爲這是換了瀏覽器的user-Agent,ip地址並沒有更換,所以當你多次運行程序時,會受到反爬蟲機制的影響,抓不到數據。
- 同步爬取,效率低,數據量小的時候感覺不出來,把國家統計局中的信息爬取到village的時候,你就會知道有多慢了(親自測試過一個省份的所有下級信息)。
推薦一個大佬的反爬蟲機制策略:
https://blog.csdn.net/ITBigGod/article/details/103248172