[Python爬蟲] 爬蟲例項:獲取政府網站公示資料並儲存到MongoDB資料庫
前言
在上一篇文章 https://blog.csdn.net/xHibiki/article/details/84134554 中,我們介紹了Mongo資料庫以及管理工具Studio3T和adminMongo的下載安裝,這次,我們結合
Python爬蟲
和第三方模組Pymongo
,爬取政府網站:深圳市規劃和國土資源委員會(市海洋局),來學習MongoDB資料庫和管理工具的的使用方法.
文件型資料庫
文件型資料庫是一類非關係型資料庫(NoSQL),MongoDB是其中的一種.區別於傳統的資料庫,它是用來管理文件。在傳統的資料庫中,資訊被分割成離散的資料段,而在文件資料庫中,文件是處理資訊的基本單位。一文件可以很長、很複雜、可以無結構,與字處理文件類似。一個文件相當於關係資料庫中的一條記錄。
文件儲存一般用類似json的格式儲存,儲存的內容是文件型的。這樣也就有機會對某些欄位建立索引,實現關係資料庫的某些功能。
在使用前,除了安裝MongoDB
和管理工具,另外還需要Pymongo
模組.
只要在命令列中輸入:pip3 install pymongo
即可安裝Pymongo庫.
或者在File–Setting–Project–Project Interpreter中獲取
爬取頁面
深圳市規劃和國土資源委員會(市海洋局)的公告公示:
隨便點開一個公告公示的詳細頁面,
包含了以下部分:
1.標題 2.來源 3.日期 4.正文 5.附件連結(0個或1個)
因為公告公示都是由同一個模板生成的,所以比較好爬取.
爬蟲程式碼
因為文章的核心是使用MongoDB和PyMongo,所以爬蟲部分就不再贅述.這裡使用requests
lxml
爬取,使用re
清洗資料
#爬取公示詳細頁面
import requests
import re
from lxml import etree
import pymongo
import time
from multiprocessing import Pool
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/67.0.3396.79 Safari/537.36'
}
# MongoDB的連線
client = pymongo.MongoClient('localhost', 27017)
mydb = client['mydb']
publicity = mydb['cn.gov.szpl.publicity']
def get_link(url): # 獲取每一頁公示的所有連結
res = requests.get(url, headers)
selector = etree.HTML(res.text)
href = selector.xpath('//ul[@class="list-group"]/li/a/@href')
links = []
for i in href:
links.append(re.sub('^.', 'http://www.szpl.gov.cn/xxgk/gggs', str(i)))
return links
def page_scratch(link): # 抓取公示詳細頁面資訊
res = requests.get(link, headers)
res.encoding = res.apparent_encoding # 更改可能的編碼方式也可以直接用"GB2312"
selector = etree.HTML(res.text)
# 公示標題
title = selector.xpath('//div[@class="xxym"]/h4/text()')[0]
# 公示來源
source = re.findall('來源:(.*)\n', selector.xpath('//div[@class="xxym"]/h5/text()')[0])[0]
# 公示日期
date = re.findall(' (.*?)\t', selector.xpath('//div[@class="xxym"]/h5/text()')[1])[0]
# 公示內容
article = '\n'.join(selector.xpath('//div[@class="TRS_Editor"]/p/text()'))
# 附件的下載連線
download_link = selector.xpath('//i[@class="fa fa-caret-right"]/a/@href')
if len(download_link) == 0:
appendix = '無'
else:
appendix = re.search('^http(.*)/', res.url)[0] + download_link[0].replace('./', '')
# 儲存到MongoDB中
publicity.insert_one({'標題': title, '來源': source, '日期': date, '公示內容': article, '附件連結': appendix})
time.sleep(0.1) # 緩衝
if __name__ == '__main__':
try:
urls = ['http://www.szpl.gov.cn/xxgk/gggs/index.html']
urls.extend(['http://www.szpl.gov.cn/xxgk/gggs/index_{}.html'.format(i) for i in range(1, 99)]) # 所有的網頁
links = []
for url in urls:
links.extend(get_link(url))
pool = Pool(processes=4)
pool.map(page_scratch, links)
except:
pass
在管理工具adminMango
可以看到抓取的頁面資訊已經成功地儲存到資料庫中
Studio3T
完整的爬蟲程式碼
多程序爬蟲,爬取共99頁的資料存放到MongoDB中.
import requests
import re
from lxml import etree
import pymongo
import time
from multiprocessing import Pool
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/67.0.3396.79 Safari/537.36'
}
# MongoDB的連線
client = pymongo.MongoClient('localhost', 27017)
mydb = client['mydb']
publicity = mydb['cn.gov.szpl.publicity']
def get_link(url): # 獲取每一頁公示的所有連結
res = requests.get(url, headers)
selector = etree.HTML(res.text)
href = selector.xpath('//ul[@class="list-group"]/li/a/@href')
links = []
for i in href:
links.append(re.sub('^.', 'http://www.szpl.gov.cn/xxgk/gggs', str(i)))
return links
def page_scratch(link): # 抓取公示詳細頁面資訊
res = requests.get(link, headers)
res.encoding = res.apparent_encoding # 更改可能的編碼方式也可以直接用"GB2312"
selector = etree.HTML(res.text)
# 公示標題
title = selector.xpath('//div[@class="xxym"]/h4/text()')[0]
# 公示來源
source = re.findall('來源:(.*)\n', selector.xpath('//div[@class="xxym"]/h5/text()')[0])[0]
# 公示日期
date = re.findall(' (.*?)\t', selector.xpath('//div[@class="xxym"]/h5/text()')[1])[0]
# 公示內容
article = '\n'.join(selector.xpath('//div[@class="TRS_Editor"]/p/text()'))
# 附件的下載連線
download_link = selector.xpath('//i[@class="fa fa-caret-right"]/a/@href')
if len(download_link) == 0:
appendix = '無'
else:
appendix = re.search('^http(.*)/', res.url)[0] + download_link[0].replace('./', '')
# 儲存到MongoDB中
publicity.insert_one({'標題': title, '來源': source, '日期': date, '公示內容': article, '附件連結': appendix})
time.sleep(0.1) # 緩衝
if __name__ == '__main__':
try:
urls = ['http://www.szpl.gov.cn/xxgk/gggs/index.html']
urls.extend(['http://www.szpl.gov.cn/xxgk/gggs/index_{}.html'.format(i) for i in range(1, 99)]) # 所有的網頁
links = []
for url in urls:
links.extend(get_link(url))
pool = Pool(processes=4)
pool.map(page_scratch, links)
except:
pass
MongoDB資料庫
爬取到了1055條資料,一頁15條應該是1485條才對,可能出不知道哪裡出了錯…有空修正一下
至於在MongoDB對資料的CRUD,我們就放到下一次來講吧~