【騰訊云 TDSQL-C Serverless 產(chǎn)品體驗(yàn)】以TDSQL-C Mysql Serverless 作為數(shù)據(jù)中心爬取豆瓣圖書數(shù)據(jù)
背景
最近我一直在研究 python
爬蟲,公司需要很多數(shù)據(jù)源的數(shù)據(jù),但遇到一個(gè)很大的障礙,就是沒(méi)有合適的數(shù)據(jù)庫(kù)儲(chǔ)存這些數(shù)據(jù),因?yàn)槠胀ǖ臋C(jī)器的性能瓶頸非常明顯,而且爬蟲數(shù)據(jù)性能的要求也不是非常穩(wěn)定,如果購(gòu)買一臺(tái)高配按月付費(fèi)的機(jī)器,那無(wú)疑浪費(fèi)了沒(méi)有使用到的性能,最近不小心看到了CSDN
首頁(yè)的推薦,發(fā)現(xiàn)正在在進(jìn)行"騰訊云TDSQL-C Serverless Mysql
數(shù)據(jù)庫(kù)體驗(yàn)活動(dòng)",我發(fā)現(xiàn) Serverless
這個(gè)特性非常符合這個(gè)場(chǎng)景,它的serverless
數(shù)據(jù)庫(kù)可以按需啟動(dòng),不需要時(shí)可關(guān)閉,而且縮放對(duì)應(yīng)用程序無(wú)影響,接下來(lái)讓我們一起來(lái)體驗(yàn)一下 TDSQL-C Serverless Mysql
吧。
TDSQL-C Serverless Mysql介紹
Serverless
服務(wù)是騰訊云自研的新一代云原生關(guān)系型數(shù)據(jù)庫(kù) TDSQL-C MySQL
版的無(wú)服務(wù)器架構(gòu)版,是全 Serverless
架構(gòu)的云原生數(shù)據(jù)庫(kù)。Serverless
服務(wù)支持按實(shí)際計(jì)算和存儲(chǔ)資源使用量收取費(fèi)用,不用不付費(fèi),其架構(gòu)如下:
-
TDSQL-C Serverless Mysql
服務(wù)架構(gòu)圖
從架構(gòu)可以看出,他有感知器對(duì)我們的數(shù)據(jù)庫(kù)節(jié)點(diǎn)進(jìn)行狀態(tài)感知,數(shù)據(jù)庫(kù)可以根據(jù)業(yè)務(wù)負(fù)載自動(dòng)啟動(dòng)停止,無(wú)感擴(kuò)縮容,擴(kuò)縮容過(guò)程不會(huì)斷開連接,并且整個(gè)使用是按實(shí)際使用的計(jì)算和存儲(chǔ)量計(jì)費(fèi),不用不付費(fèi),按秒計(jì)量,按小時(shí)結(jié)算。
官方也給出了一些適用場(chǎng)景,我發(fā)現(xiàn)和我的需求還比較類似:
以TDSQL-C Mysql Serverless 作為數(shù)據(jù)中心爬取豆瓣圖書數(shù)據(jù)
既然是體驗(yàn),那必然要深入使用一下,這里我通過(guò)構(gòu)建一個(gè) TDSQL-C Mysql Serverless
單節(jié)點(diǎn),進(jìn)行豆瓣圖書的數(shù)據(jù)存儲(chǔ),使用的是 scrapy
框架,主要是對(duì) top250
和評(píng)論的數(shù)據(jù)進(jìn)行爬取,然后轉(zhuǎn)存,最后也對(duì)整個(gè) CCU
的擴(kuò)縮進(jìn)行了監(jiān)測(cè),發(fā)現(xiàn)確實(shí)可以非常絲滑進(jìn)行實(shí)例的擴(kuò)縮,并且對(duì)上層程序沒(méi)有任何影響,接下來(lái)跟著我的步驟一起來(lái)體驗(yàn)吧~
1、TDSQL-C Mysql Serverless環(huán)境構(gòu)建
這里我們采用最小配置就可以了,我的配置如下:
- 版本:mysql8.0
- 類型:serverless
- 架構(gòu):?jiǎn)喂?jié)點(diǎn)
- 算力:min 0.5 max2
不需要我們和原始一樣自己在服務(wù)器上進(jìn)行mysql
下載和安裝了,直接購(gòu)買會(huì)自動(dòng)生成一個(gè)高可用高性能的云數(shù)據(jù)庫(kù),非常的便捷?。?/p>
2、登錄DMC進(jìn)行數(shù)據(jù)表構(gòu)建
數(shù)據(jù)庫(kù)管理(DMC)是一個(gè)高效、可靠的一站式數(shù)據(jù)庫(kù)管理平臺(tái),是騰訊云專門研發(fā)的 web
數(shù)據(jù)庫(kù)管理平臺(tái),可以更加便捷、規(guī)范地管理多種數(shù)據(jù)庫(kù)實(shí)例。
- 新建一個(gè)
douban
的數(shù)據(jù)庫(kù) - 建立 book 表和 book_comment 表
CREATE TABLE `book_comments` (
`id` int NOT NULL AUTO_INCREMENT,
`book_id` int NOT NULL,
`book_name` varchar(100) NOT NULL,
`username` varchar(30) NOT NULL,
`rating` int DEFAULT NULL,
`comment_time` datetime DEFAULT CURRENT_TIMESTAMP,
`useful_count` int DEFAULT '0',
`content` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
CREATE TABLE `books` (
`id` int NOT NULL AUTO_INCREMENT,
`book_id` int DEFAULT NULL,
`title` varchar(100) NOT NULL,
`cover` varchar(200) DEFAULT NULL,
`is_try_read` varchar(1) DEFAULT NULL,
`author` varchar(30) NOT NULL,
`publisher` varchar(50) DEFAULT NULL,
`publish_date` varchar(30) DEFAULT NULL,
`list_price` varchar(30) DEFAULT NULL,
`rating` float DEFAULT NULL,
`ratings_count` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=206 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
點(diǎn)擊SQL
窗口即可喚出,有了基礎(chǔ)數(shù)據(jù)表之后,我們就需要進(jìn)一步去搭建我們的開發(fā)環(huán)境,因?yàn)閿?shù)據(jù)庫(kù)很多參數(shù)、調(diào)優(yōu)等騰訊云已經(jīng)幫我們處理了,我們只需要使用即可,我們首先把數(shù)據(jù)庫(kù)的公網(wǎng)訪問(wèn)打開,在節(jié)點(diǎn)詳情中
這樣就是打開的狀態(tài),我們?cè)陂_發(fā)環(huán)境中就可以使用這個(gè) 主機(jī)+端口以及自己購(gòu)買時(shí)的賬號(hào)密碼 進(jìn)行連接
3、搭建爬蟲項(xiàng)目
3.1 、基礎(chǔ)scrapy框架搭建
- 安裝 scrapy
pip install scrapy
- 創(chuàng)建scrapy工程
scrapy startproject 項(xiàng)目名稱
- 創(chuàng)建圖書爬蟲和評(píng)論爬蟲
scrapy genspider 爬蟲名 域名
這個(gè)時(shí)候,整個(gè)項(xiàng)目框架如下圖所示:
- 依賴管理
為了方便依賴的管理和項(xiàng)目的遷移,我定義了一份 requirements.txt
文件,內(nèi)容如下:
scrapy
pymysql
- 安裝依賴
pip install -r requirement.txt
scrapy
就是我們的爬蟲框架,pymysql
是用來(lái)連接我們的 TDSQL
數(shù)據(jù)庫(kù)的
這樣就完成了最基礎(chǔ)的框架搭建,然后我們主要對(duì)以下幾個(gè)文件進(jìn)行開發(fā)和修改:
- book_spider.py 圖書的爬蟲(需開發(fā))
- book_comment_spider.py 圖書評(píng)論的爬蟲(需開發(fā))
- items.py ORM文件(需開發(fā))
- pipelines.py 管道文件,用來(lái)將數(shù)據(jù)存儲(chǔ)到 TDSQL (需開發(fā))
- settings.py 配置文件(需要修改)
我們首先將 TDSQL-C Serverless Mysql 集成到項(xiàng)目中
3.2 、根據(jù)數(shù)據(jù)表構(gòu)建ORM
在 items.py 中增加兩個(gè)模型映射,代碼如下:
class DoubanBooksItem(scrapy.Item):
book_id = scrapy.Field()
title = scrapy.Field()
cover_link = scrapy.Field()
is_try_read = scrapy.Field()
author = scrapy.Field()
publisher = scrapy.Field()
publish_date = scrapy.Field()
price = scrapy.Field()
rating = scrapy.Field()
rating_count = scrapy.Field()
class DoubanBookCommentItem(scrapy.Item):
book_id = scrapy.Field()
book_name = scrapy.Field()
username = scrapy.Field()
rating = scrapy.Field()
comment_time = scrapy.Field()
useful_count = scrapy.Field()
content = scrapy.Field()
3.3 、集成TDSQL-C ServerLess Mysql
- 增加數(shù)據(jù)庫(kù)配置
在文件最尾部增加 DATABASE 配置:
DATABASE = {
'host': 'gz-cynosdbmysql-grp-k2z7kdln.sql.tencentcdb.com',
'port': 21194,
'user': 'root',
'passwd': 'Qwerabc.',
'db': 'douban',
'charset': 'utf8',
}
- 增加 pipelines 配置
ITEM_PIPELINES = {
'douban_books.pipelines.DoubanBookCommentTDSQLPipeline': 1,
}
這是我們下一步需要開發(fā)的 pipeline
3.4 、開發(fā) DoubanBookCommentTDSQLPipeline
因?yàn)槲覀冇袃蓚€(gè)不同的 item
,所以我們會(huì)在 process_item
中進(jìn)行判斷
from twisted.enterprise import adbapi
from douban_books.items import DoubanBooksItem, DoubanBookCommentItem
from douban_books.settings import DATABASE
class DoubanBookCommentTDSQLPipeline:
def __init__(self):
self.conn = adbapi.ConnectionPool('pymysql', **DATABASE)
def do_insert_book(self, tx, item):
# 執(zhí)行插入操作
tx.execute("""insert into books (book_id, title, cover, is_try_read, author, publisher, publish_date, list_price, rating, ratings_count) values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)""", (item['book_id'], item['title'], item['cover_link'], item['is_try_read'], item['author'], item['publisher'], item['publish_date'], item['price'], item['rating'], item['rating_count']))
def do_insert_book_comment(self, tx, item):
# 執(zhí)行插入操作
tx.execute("""insert into books (book_id, book_name, username, rating, comment_time, useful_count, content) values (%s,%s,%s,%s,%s,%s,%s)""", (item['book_id'], item['book_name'], item['username'], item['rating'], item['comment_time'], item['useful_count'], item['content']))
def process_item(self, item, spider):
if isinstance(item, DoubanBooksItem):
print('開始寫入 book')
query = self.conn.runInteraction(self.do_insert_book, item)
query.addErrback(self.handle_error)
elif isinstance(item, DoubanBookCommentItem):
print(item)
print('開始寫入 book item')
query = self.conn.runInteraction(self.do_insert_book_comment, item)
query.addErrback(self.handle_error)
return item
def handle_error(self, failure):
# 處理異步插入的錯(cuò)誤
print(failure)
3.5 、開發(fā)豆瓣圖書爬蟲
這里我們主要爬取 top250
的圖書,爬蟲的數(shù)據(jù)會(huì)最后會(huì)通過(guò) pipeline
轉(zhuǎn)存到 TDSQL-C ServerLess
import scrapy
from douban_books.items import DoubanBooksItem
import re
class DoubanBookSpider(scrapy.Spider):
name = 'douban_book_spider'
start_urls = ['https://book.douban.com/top250']
def parse(self, response):
# 解析書籍信息
for book_tr in response.css('tr.item'):
item = DoubanBooksItem()
# 提取書籍URL
book_url = book_tr.css('div.pl2 > a::attr(href)').get()
# 提取書籍ID
item['book_id'] = book_url.split('/')[-2] if book_url else None
item['title'] = book_tr.css('div.pl2 a::text').get().strip()
item['cover_link'] = book_tr.css('td a.nbg img::attr(src)').get()
item['is_try_read'] = "是" if book_tr.css('div.pl2 img[title="可試讀"]') else "否"
# 提取作者、出版社、發(fā)行日期和價(jià)格的信息
details = book_tr.css('p.pl::text').get().strip().split(' / ')
item['author'] = details[0]
item['publisher'] = details[-3]
item['publish_date'] = details[-2]
item['price'] = details[-1]
item['rating'] = book_tr.css('span.rating_nums::text').get()
rating_count_text = book_tr.css('span.pl::text').get()
item['rating_count'] = re.search(r'(\d+)人評(píng)價(jià)', rating_count_text).group(1) if rating_count_text else None
yield item
# 翻頁(yè)處理
next_page = response.css('span.next a::attr(href)').get()
if next_page:
yield scrapy.Request(url=response.urljoin(next_page), callback=self.parse)
現(xiàn)在我們可以對(duì)這個(gè)爬蟲進(jìn)行運(yùn)行測(cè)試爬取
scrapy crawl douban_book_spider
- 通過(guò)
DMC
查看數(shù)據(jù)是否正常寫入
3.6 、開發(fā)豆瓣圖書評(píng)論爬蟲
這里我們要通過(guò) TDSQL-C
獲取所有爬取的圖書的 id
,進(jìn)行評(píng)論獲取
import pymysql
import scrapy
import json
from douban_books.items import DoubanBookCommentItem
from douban_books.settings import DATABASE
class DoubanBookCommentSpider(scrapy.Spider):
name = 'douban_book_comment_spider'
db = pymysql.connect(**DATABASE)
# 使用Cursor執(zhí)行SQL
cursor = db.cursor()
sql = "SELECT book_id FROM books"
cursor.execute(sql)
# 獲取結(jié)果
results = cursor.fetchall()
# 提取book_id
book_ids = [result[0] for result in results]
# Step 2: Generate start_urls from book.csv
start_urls = [f'https://book.douban.com/subject/{book_id}/' for book_id in book_ids]
def parse(self, response):
self.logger.info(f"Parsing: {response.url}")
# Extract music name
book_title = response.css('h1 span::text').get()
print(book_title)
# Construct the initial comments URL
book_id = response.url.split("/")[4]
comments_url = f'https://book.douban.com/subject/{book_id}/comments/?start=0&limit=20&status=P&sort=new_score&comments_only=1'
print(comments_url)
yield scrapy.Request(url=comments_url, callback=self.parse_comments, meta={'book_title': book_title, 'book_id': book_id})
def parse_comments(self, response):
# Extract the HTML content from the JSON data
html_content = response.json()['html']
selector = scrapy.Selector(text=html_content)
book_name = response.meta['book_title']
book_id = response.meta['book_id']
data = json.loads(response.text)
print(selector.css('li.comment-item'))
# 解析評(píng)論
for comment in selector.css('li.comment-item'):
item = DoubanBookCommentItem()
item['book_id'] = book_id
item['book_name'] = book_name
item['username'] = comment.css('a::attr(title)').get()
item['rating'] = comment.css('.comment-info span.rating::attr(title)').get()
# rating_class = comment.css('span.rating::attr(class)').get()
# item['rating'] = self.parse_rating(rating_class) if rating_class else None
item['comment_time'] = comment.css('span.comment-info > a.comment-time::text').get()
# item['comment_time'] = comment.css('span.comment-time::text').get()
item['useful_count'] = comment.css('span.vote-count::text').get()
item['content'] = comment.css('span.short::text').get()
yield item
book_id = response.url.split("/")[4]
base_url = f"https://book.douban.com/subject/{book_id}/comments/"
next_page = selector.css('#paginator a[data-page="next"]::attr(href)').get()
if next_page:
next_page_url = base_url + next_page + '&comments_only=1'
yield scrapy.Request(url=next_page_url, callback=self.parse_comments, meta={'book_title': book_name, 'book_id': book_id})
- 運(yùn)行評(píng)論爬蟲
scrapy crawl douban_book_comment_spider
3.7 、CCU的擴(kuò)縮
為什么購(gòu)買 TDSQL-C ServerLess Mysql
的時(shí)候需要選擇一個(gè) min 和 max 的算力配置,那是因?yàn)?Serverless
的一大特點(diǎn)就是自動(dòng)進(jìn)行擴(kuò)縮,TDSQL-C Serverless Mysql
是根據(jù)CCU
選擇資源范圍自動(dòng)進(jìn)行彈性擴(kuò)縮容,一個(gè) CCU
近似等于1個(gè) CPU
和 2GB
內(nèi)存的計(jì)算資源,每個(gè)計(jì)費(fèi)周期的 CCU
使用數(shù)量為:數(shù)據(jù)庫(kù)所使用的 CPU 核數(shù) 與 內(nèi)存大小的1/2 二者中取最大值。
根據(jù)我們的算力上限 max 2
,也就是當(dāng)我們有大流量進(jìn)來(lái)的時(shí)候最大會(huì)幫我們把數(shù)據(jù)庫(kù)擴(kuò)容成近似 2CPU+4GB
的機(jī)器。
在我們進(jìn)行爬蟲的時(shí)候,經(jīng)常會(huì)需要分布式爬蟲,而多數(shù)據(jù)源的爬取對(duì)于數(shù)據(jù)庫(kù)是一個(gè)不小的挑戰(zhàn),爬蟲的性能也和數(shù)據(jù)庫(kù)直接掛鉤,我在進(jìn)行多線程爬蟲的時(shí)候就發(fā)現(xiàn)我們的 Serverless
數(shù)據(jù)庫(kù)在自動(dòng)擴(kuò)縮:
這里我準(zhǔn)備了 20 個(gè)數(shù)據(jù)據(jù)源,是以前積累的,同時(shí)進(jìn)行分布式爬取,大約數(shù)據(jù) 3000w
,讓我們一起來(lái)觀察一下 服務(wù)器的狀態(tài)
- CPU
- CCU擴(kuò)縮狀態(tài)
- 寫請(qǐng)求IOPS
從這也可以看出寫入是的性能也是逐步攀升的
體驗(yàn)總結(jié)
通過(guò)這次對(duì)TDSQL-C Serverless Mysql
的體驗(yàn),我對(duì)它也有了更深入的了解,后續(xù)會(huì)向公司推薦使用,確實(shí)很爽,我也總結(jié)一下本次的感受:
- 在應(yīng)用方面
TDSQL-C Serverless Mysql
適用于數(shù)據(jù)采集、分析和實(shí)時(shí)計(jì)算等動(dòng)態(tài)負(fù)載場(chǎng)景。比如我們這個(gè)爬蟲項(xiàng)目,隨著數(shù)據(jù)量的增加,它可以自動(dòng)進(jìn)行擴(kuò)容,滿足性能需求。這對(duì)傳統(tǒng)的數(shù)據(jù)庫(kù)架構(gòu)來(lái)說(shuō)是難以實(shí)現(xiàn)的。
- 在使用體驗(yàn)方面
TDSQL-C Serverless Mysql
最大的優(yōu)勢(shì)就是無(wú)需運(yùn)維,我們只需關(guān)注業(yè)務(wù)開發(fā)本身。它采用了Serverless架構(gòu),我們無(wú)需購(gòu)買和管理硬件,也無(wú)需監(jiān)控調(diào)優(yōu)數(shù)據(jù)庫(kù)。這大大提升了開發(fā)效率。
- 在經(jīng)濟(jì)效益方面
TDSQL-C Serverless Mysql
采用按用量付費(fèi)的模式,成本更為精準(zhǔn)合理。不需要為了閑置資源付費(fèi)。且資源會(huì)根據(jù)負(fù)載自動(dòng)彈性伸縮。這對(duì)節(jié)約IT成本簡(jiǎn)直不要太棒~文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-714954.html
總體來(lái)說(shuō)。TDSQL-C Mysql
作為Serverless
數(shù)據(jù)庫(kù),已經(jīng)非常完備了,可用性也非常高。對(duì)于諸如數(shù)據(jù)采集這樣無(wú)界資源需求的場(chǎng)景尤其適用。相信隨著更多客戶的驗(yàn)證和云技術(shù)的發(fā)展,它會(huì)發(fā)展的越來(lái)越好,今后我也會(huì)繼續(xù)關(guān)注 TDSQL-C Serverless Mysql
的更新,并在合適的機(jī)會(huì)中將其應(yīng)用到其他業(yè)務(wù)項(xiàng)目中,希望它能夠帶來(lái)更多的價(jià)值,文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-714954.html
到了這里,關(guān)于【騰訊云 TDSQL-C Serverless 產(chǎn)品體驗(yàn)】以TDSQL-C Mysql Serverless 作為數(shù)據(jù)中心爬取豆瓣圖書數(shù)據(jù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!