1. 程式人生 > >[Python爬蟲] 爬蟲例項:獲取政府網站公示資料並儲存到MongoDB資料庫

[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,我們就放到下一次來講吧~