Python3爬蟲資料入資料庫---把爬取到的資料存到資料庫,帶資料庫去重功能

碼農小石頭發表於2018-10-22

這是python3實戰入門系列的第三篇文章,要學習這一篇需要了解前兩篇,要不學起來比較費勁

下面來正式開始把我們第一節爬取到的新聞資料儲存到mysql資料中

一,首先我們需要連線資料庫

通過定義一個MySQLCommand類來配置資料庫連線引數,並定義一個connectMysql方法連線資料庫

# -*- coding: utf-8 -*-
# 作者微信:2501902696
import pymysql
# 用來運算元據庫的類
class MySQLCommand(object):
    # 類的初始化
    def __init__(self):
        self.host = 'localhost'
        self.port = 3306  # 埠號
        self.user = 'root'  # 使用者名稱
        self.password = ""  # 密碼
        self.db = "home"  # 庫
        self.table = "home_list"  # 表

    # 連結資料庫
    def connectMysql(self):
        try:
            self.conn = pymysql.connect(host=self.host, port=self.port, user=self.user,
                                        passwd=self.password, db=self.db, charset='utf8')
            self.cursor = self.conn.cursor()
        except:
            print('connect mysql error.')
複製程式碼

二,連線完資料庫後我們需要插入資料了

插入資料之前我們有兩個問題

  • 1,重複的資料如何去重
  • 2,新資料的主鍵id應該從哪裡開始 針對上面的兩個問題我貼出一部分程式碼來看解決思路
# 插入資料,插入之前先查詢是否存在,如果存在就不再插入
    def insertData(self, my_dict):
        table = "home_list"  # 要操作的表格
        # 注意,這裡查詢的sql語句url=' %s '中%s的前後要有空格
        sqlExit = "SELECT url FROM home_list  WHERE url = ' %s '" % (my_dict['url'])
        res = self.cursor.execute(sqlExit)
        if res:  # res為查詢到的資料條數如果大於0就代表資料已經存在
            print("資料已存在", res)
            return 0
        # 資料不存在才執行下面的插入操作
        try:
            cols = ', '.join(my_dict.keys())#用,分割
            values = '"," '.join(my_dict.values())
            sql = "INSERT INTO home_list (%s) VALUES (%s)" % (cols, '"' + values + '"')
            #拼裝後的sql如下
            # INSERT INTO home_list (img_path, url, id, title) VALUES ("https://img.huxiucdn.com.jpg"," https://www.huxiu.com90.html"," 12"," ")
            try:
                result = self.cursor.execute(sql)
                insert_id = self.conn.insert_id()  # 插入成功後返回的id
                self.conn.commit()
                # 判斷是否執行成功
                if result:
                    print("插入成功", insert_id)
                    return insert_id + 1
            except pymysql.Error as e:
                # 發生錯誤時回滾
                self.conn.rollback()
                # 主鍵唯一,無法插入
                if "key 'PRIMARY'" in e.args[1]:
                    print("資料已存在,未插入資料")
                else:
                    print("插入資料失敗,原因 %d: %s" % (e.args[0], e.args[1]))
        except pymysql.Error as e:
            print("資料庫錯誤,原因%d: %s" % (e.args[0], e.args[1]))
複製程式碼
通過上面程式碼我們來看如何去重
  • 我們在每次插入之前需要查詢下資料是否已經存在,如果存在就不在插入,我們的home_list表格的欄位有 id,title,url,img_path。通過分析我們抓取到的資料titlehe和img_path欄位都可能為空,所以這裡我們通過url欄位來去重。知道去重原理以後再去讀上面的程式碼,你應該能容易理解了

三,查詢資料庫中最後一條資料的id值,來確定我們新資料id的開始值

通過下面的getLastId函式來獲取home_list表裡的最後一條資料的id值

# 查詢最後一條資料的id值
    def getLastId(self):
        sql = "SELECT max(id) FROM " + self.table
        try:
            self.cursor.execute(sql)
            row = self.cursor.fetchone()  # 獲取查詢到的第一條資料
            if row[0]:
                return row[0]  # 返回最後一條資料的id
            else:
                return 0  # 如果表格為空就返回0
        except:
            print(sql + ' execute failed.')
複製程式碼

下面貼出MySQLCommand資料庫操作類的完整程式碼

# -*- coding: utf-8 -*-
# 作者微信:2501902696
import pymysql
# 用來運算元據庫的類
class MySQLCommand(object):
    # 類的初始化
    def __init__(self):
        self.host = 'localhost'
        self.port = 3306  # 埠號
        self.user = 'root'  # 使用者名稱
        self.password = ""  # 密碼
        self.db = "home"  # 庫
        self.table = "home_list"  # 表

    # 連結資料庫
    def connectMysql(self):
        try:
            self.conn = pymysql.connect(host=self.host, port=self.port, user=self.user,
                                        passwd=self.password, db=self.db, charset='utf8')
            self.cursor = self.conn.cursor()
        except:
            print('connect mysql error.')

    # 插入資料,插入之前先查詢是否存在,如果存在就不再插入
    def insertData(self, my_dict):
        table = "home_list"  # 要操作的表格
        # 注意,這裡查詢的sql語句url=' %s '中%s的前後要有空格
        sqlExit = "SELECT url FROM home_list  WHERE url = ' %s '" % (my_dict['url'])
        res = self.cursor.execute(sqlExit)
        if res:  # res為查詢到的資料條數如果大於0就代表資料已經存在
            print("資料已存在", res)
            return 0
        # 資料不存在才執行下面的插入操作
        try:
            cols = ', '.join(my_dict.keys())#用,分割
            values = '"," '.join(my_dict.values())
            sql = "INSERT INTO home_list (%s) VALUES (%s)" % (cols, '"' + values + '"')
            #拼裝後的sql如下
            # INSERT INTO home_list (img_path, url, id, title) VALUES ("https://img.huxiucdn.com.jpg"," https://www.huxiu.com90.html"," 12"," ")
            try:
                result = self.cursor.execute(sql)
                insert_id = self.conn.insert_id()  # 插入成功後返回的id
                self.conn.commit()
                # 判斷是否執行成功
                if result:
                    print("插入成功", insert_id)
                    return insert_id + 1
            except pymysql.Error as e:
                # 發生錯誤時回滾
                self.conn.rollback()
                # 主鍵唯一,無法插入
                if "key 'PRIMARY'" in e.args[1]:
                    print("資料已存在,未插入資料")
                else:
                    print("插入資料失敗,原因 %d: %s" % (e.args[0], e.args[1]))
        except pymysql.Error as e:
            print("資料庫錯誤,原因%d: %s" % (e.args[0], e.args[1]))

    # 查詢最後一條資料的id值
    def getLastId(self):
        sql = "SELECT max(id) FROM " + self.table
        try:
            self.cursor.execute(sql)
            row = self.cursor.fetchone()  # 獲取查詢到的第一條資料
            if row[0]:
                return row[0]  # 返回最後一條資料的id
            else:
                return 0  # 如果表格為空就返回0
        except:
            print(sql + ' execute failed.')

    def closeMysql(self):
        self.cursor.close()
        self.conn.close()  # 建立資料庫操作類的例項
複製程式碼

再貼出把爬蟲爬取資料插入到資料庫的程式碼

# -*- coding: utf-8 -*-
# 作者微信:2501902696
from bs4 import BeautifulSoup
from urllib import request
import chardet

from db.MySQLCommand import MySQLCommand

url = "https://www.huxiu.com"
response = request.urlopen(url)
html = response.read()
charset = chardet.detect(html)
html = html.decode(str(charset["encoding"]))  # 設定抓取到的html的編碼方式

# 使用剖析器為html.parser
soup = BeautifulSoup(html, 'html.parser')
# 獲取到每一個class=hot-article-img的a節點
allList = soup.select('.hot-article-img')

# 連線資料庫
mysqlCommand = MySQLCommand()
mysqlCommand.connectMysql()
#這裡每次查詢資料庫中最後一條資料的id,新加的資料每成功插入一條id+1
dataCount = int(mysqlCommand.getLastId()) + 1
for news in allList:  # 遍歷列表,獲取有效資訊
    aaa = news.select('a')
    # 只選擇長度大於0的結果
    if len(aaa) > 0:
        # 文章連結
        try:  # 如果丟擲異常就代表為空
            href = url + aaa[0]['href']
        except Exception:
            href = ''
        # 文章圖片url
        try:
            imgUrl = aaa[0].select('img')[0]['src']
        except Exception:
            imgUrl = ""
        # 新聞標題
        try:
            title = aaa[0]['title']
        except Exception:
            title = ""

        #把爬取到的每條資料組合成一個字典用於資料庫資料的插入
        news_dict = {
            "id": str(dataCount),
            "title": title,
            "url": href,
            "img_path": imgUrl
        }
        try:
            # 插入資料,如果已經存在就不在重複插入
            res = mysqlCommand.insertData(news_dict)
            if res:
                dataCount=res
        except Exception as e:
            print("插入資料失敗", str(e))#輸出插入失敗的報錯語句
mysqlCommand.closeMysql()  # 最後一定要要把資料關閉
dataCount=0
複製程式碼

如果對上面程式碼不是很瞭解可以到我的第一節文章去看下 python3實戰入門python爬蟲篇---網頁爬蟲,圖片爬蟲,文章爬蟲,Python爬蟲爬取新聞網站新聞

到此我們的python3爬蟲+python3資料庫篇就完事了,看下操作效果圖

GIF.gif
gif圖片質量不是很好,大家湊合著看吧☺☺☹☎

寫於---Python零基礎實戰入門第四天

相關文章