国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - python使用adbapi實(shí)現(xiàn)MySQL數(shù)據(jù)庫的異步存儲

python使用adbapi實(shí)現(xiàn)MySQL數(shù)據(jù)庫的異步存儲

2021-06-07 00:51Wilson_Iceman Python

這篇文章主要為大家詳細(xì)介紹了python使用adbapi實(shí)現(xiàn)MySQL數(shù)據(jù)庫的異步存儲,具有一定的參考價值,感興趣的小伙伴們可以參考一下

之前一直在寫有關(guān)scrapy爬蟲的事情,今天我們看看使用scrapy如何把爬到的數(shù)據(jù)放在mysql數(shù)據(jù)庫中保存。

有關(guān)python操作mysql數(shù)據(jù)庫的內(nèi)容,網(wǎng)上已經(jīng)有很多內(nèi)容可以參考了,但都是在同步的操作mysql數(shù)據(jù)庫。在數(shù)據(jù)量不大的情況下,這種方法固然可以,但是一旦數(shù)據(jù)量增長后,mysql就會出現(xiàn)崩潰的情況,因?yàn)榫W(wǎng)上爬蟲的速度要遠(yuǎn)遠(yuǎn)高過往數(shù)據(jù)庫中插入數(shù)據(jù)的速度。為了避免這種情況發(fā)生,我們就需要使用異步的方法來存儲數(shù)據(jù),爬蟲與數(shù)據(jù)存儲互不影響。

為了顯示方便,我們把程序設(shè)計的簡單一點(diǎn),只是爬一頁的數(shù)據(jù)。我們今天選擇伯樂在線這個網(wǎng)站來爬取,只爬取第一頁的數(shù)據(jù)。

首先我們還是要啟動一個爬蟲項目,然后自己建了一個爬蟲的文件jobbole.py。我們先來看看這個文件中的代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# -*- coding: utf-8 -*-
import io
import sys
import scrapy
import re
import datetime
from scrapy.http import request
from urllib import parse
from articlespider.items import jobbolearticleitem, articleitemloader
from scrapy.loader import itemloader
sys.stdout = io.textiowrapper(sys.stdout.buffer,encoding='utf-8')
 
class jobbolespider(scrapy.spider):
 """docstring for jobbolespider"""
 name = "jobbole"
 allowed_domain = ["blog.jobbole.com"]
 start_urls = ['http://blog.jobbole.com/all-posts/']
 
 def parse(self, response):
 """
 1.獲取列表頁中的文章url
 """
 # 解析列表匯中所有文章url并交給scrapy下載器并進(jìn)行解析
 post_nodes = response.css("#archive .floated-thumb .post-thumb a")
 for post_node in post_nodes:
 image_url = post_node.css("img::attr(src)").extract_first("")# 這里取出每篇文章的封面圖,并作為meta傳入request
 post_url = post_node.css("::attr(href)").extract_first("")
 yield request(url = parse.urljoin(response.url, post_url), meta = {"front_image_url":image_url}, callback = self.parse_detail)
 
 def parse_detail(self, response):
 article_item = jobbolearticleitem()
 # 通過itemloader加載item
 # 通過add_css后的返回值都是list型,所有我們再items.py要進(jìn)行處理
 item_loader = articleitemloader(item = jobbolearticleitem(), response = response)
 item_loader.add_css("title", ".entry-header h1::text")
 item_loader.add_value("url", response.url)
 # item_loader.add_value("url_object_id", get_md5(response.url))
 item_loader.add_value("url_object_id", response.url)
 item_loader.add_css("create_date", "p.entry-meta-hide-on-mobile::text")
 item_loader.add_value("front_image_url", [front_image_url])
 item_loader.add_css("praise_nums", ".vote-post-up h10::text")
 item_loader.add_css("comment_nums", "a[href='#article-comment'] span::text")
 item_loader.add_css("fav_nums", ".bookmark-btn::text")
 item_loader.add_css("tags", "p.entry-meta-hide-on-mobile a::text")
 item_loader.add_css("content", "div.entry")
 
 article_item = item_loader.load_item()
 print(article_item["tags"])
 
 yield article_item
 pass

這里我把代碼進(jìn)行了簡化,首先對列表頁發(fā)出請求,這里只爬取一頁數(shù)據(jù),然后分析每一頁的url,并且交給scrapy對每一個url進(jìn)行請求,得到每篇文章的詳情頁,把詳情頁的相關(guān)內(nèi)容放在mysql數(shù)據(jù)庫中。
這里使用itemloader來進(jìn)行頁面的解析,這樣解析有個最大的好處就是可以把解析規(guī)則存放在數(shù)據(jù)庫中,實(shí)現(xiàn)對解析規(guī)則的動態(tài)加載。但是要注意一點(diǎn)是使用itemloader中css方式和xpath方式得到的數(shù)據(jù)都是list型,因此還需要在items.py中再對相對應(yīng)的數(shù)據(jù)進(jìn)行處理。

接下來我們就來看看items.py是如何處理list數(shù)據(jù)的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# -*- coding: utf-8 -*-
 
# define here the models for your scraped items
#
# see documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html
import datetime
import re
 
 
import scrapy
from scrapy.loader import itemloader
from scrapy.loader.processors import mapcompose, takefirst,join
from articlespider.utils.common import get_md5
 
 
def convert_date(value):
 try:
 create_date = datetime.datetime.strptime(create_date, "%y/%m/%d").date()
 except exception as e:
 create_date = datetime.datetime.now().date()
 return create_date
 
def get_nums(value):
 match_re = re.match(".*?(\d+).*", value)
 if match_re:
 nums = int(match_re.group(1))
 else:
 nums = 0
 
 return nums
 
def remove_comment_tags(value):
 # 去掉tags中的評論內(nèi)容
 if "評論" in value:
 # 這里做了修改,如果返回"",則在list中仍然會占位,會變成類似于["程序員",,"解鎖"]這樣
 # return ""
 return none
 else:
 return value
 
def return_value(value):
 return
 
class articleitemloader(itemloader):
 """docstring for ariticleitemloader"""
 # 自定義itemloader
 default_output_processor = takefirst()
 
class articlespideritem(scrapy.item):
 # define the fields for your item here like:
 # name = scrapy.field()
 pass
 
class jobbolearticleitem(scrapy.item):
 """docstring for articlespideritem"""
 title = scrapy.field()
 create_date = scrapy.field(
 input_processor = mapcompose(convert_date)
 )
 url = scrapy.field()
 url_object_id = scrapy.field(
 output_processor = mapcompose(get_md5)
 )
 # 這里注意front_image_url還是一個list,在進(jìn)行sql語句時還需要處理
 front_image_url = scrapy.field(
 output_processor = mapcompose(return_value)
 )
 front_image_path = scrapy.field()
 praise_nums = scrapy.field(
 input_processor = mapcompose(get_nums)
 )
 comment_nums = scrapy.field(
 input_processor = mapcompose(get_nums)
 )
 fav_nums = scrapy.field(
 input_processor = mapcompose(get_nums)
 )
 # tags要做另行處理,因?yàn)閠ags我們需要的就是list
 tags = scrapy.field(
 input_processor = mapcompose(remove_comment_tags),
 output_processor = join(",")
 )
 content = scrapy.field()

首先我們看到定義了一個類articleitemloader,在這個類中只有一句話,就是對于每個items都默認(rèn)采用list中的第一個元素,這樣我們就可以把每個items中的第一個元素取出來。但是要注意,有些items我們是必須要用list型的,比如我們給imagepipeline的數(shù)據(jù)就要求必須是list型,這樣我們就需要對front_image_url單獨(dú)進(jìn)行處理。這里我們做了一個小技巧,對front_image_url什么都不錯,因?yàn)槲覀儌鬟^來的front_image_url就是list型
在items的field中有兩個參數(shù),一個是input_processor,另一個是output_processor,這兩個參數(shù)可以幫助我們對items的list中的每個元素進(jìn)行處理,比如有些需要用md5進(jìn)行加密,有些需要用正則表達(dá)式進(jìn)行篩選或者排序等等。

在進(jìn)行mysql的pipeline之前,我們需要設(shè)計數(shù)據(jù)庫,下面是我自己設(shè)計的數(shù)據(jù)庫的字段,僅供參考

python使用adbapi實(shí)現(xiàn)MySQL數(shù)據(jù)庫的異步存儲

這里我把url_object_id作為該表的主鍵,由于它不會重復(fù),所以適合做主鍵。

下面我們來看看數(shù)據(jù)庫的pipeline。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# -*- coding: utf-8 -*-
 
# define your item pipelines here
#
# don't forget to add your pipeline to the item_pipelines setting
# see: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
import codecs
import json
from twisted.enterprise import adbapi
import mysqldb
import mysqldb.cursors
 
 
class mysqltwistedpipeline(object):
 """docstring for mysqltwistedpipeline"""
 #采用異步的機(jī)制寫入mysql
 def __init__(self, dbpool):
 self.dbpool = dbpool
 
 @classmethod
 def from_settings(cls, settings):
 dbparms = dict(
 host = settings["mysql_host"],
 db = settings["mysql_dbname"],
 user = settings["mysql_user"],
 passwd = settings["mysql_password"],
 charset='utf8',
 cursorclass=mysqldb.cursors.dictcursor,
 use_unicode=true,
 )
 dbpool = adbapi.connectionpool("mysqldb", **dbparms)
 
 return cls(dbpool)
 
 def process_item(self, item, spider):
 #使用twisted將mysql插入變成異步執(zhí)行
 query = self.dbpool.runinteraction(self.do_insert, item)
 query.adderrback(self.handle_error, item, spider) #處理異常
 return item
 
 def handle_error(self, failure, item, spider):
 # 處理異步插入的異常
 print (failure)
 
 def do_insert(self, cursor, item):
 #執(zhí)行具體的插入
 #根據(jù)不同的item 構(gòu)建不同的sql語句并插入到mysql中
 # insert_sql, params = item.get_insert_sql()
 # print (insert_sql, params)
 # cursor.execute(insert_sql, params)
 insert_sql = """
 insert into jobbole_article(title, url, create_date, fav_nums, url_object_id)
 values (%s, %s, %s, %s, %s)
 """
 # 可以只使用execute,而不需要再使用commit函數(shù)
 cursor.execute(insert_sql, (item["title"], item["url"], item["create_date"], item["fav_nums"], item["url_object_id"]))

在這里我們只是演示一下,我們只向數(shù)據(jù)庫中插入5個字段的數(shù)據(jù),分別是title,url,create_date,fav_nums,url_object_id。

當(dāng)然你也可以再加入其它的字段。

首先我們看看from_settings這個函數(shù),它可以從settings.py文件中取出我們想想要的數(shù)據(jù),這里我們把數(shù)據(jù)庫的host,dbname,username和password都放在settings.py中。實(shí)際的插入語句還是在process_item中進(jìn)行,我們自己定義了一個函數(shù)do_insert,然后把它傳給dbpool中用于插入真正的數(shù)據(jù)。

最后我們來看看settings.py中的代碼,這里就很簡單了。

?
1
2
3
4
mysql_host = "localhost"
mysql_dbname = "article_wilson"
mysql_user = "root"
mysql_password = "root"

其實(shí)這里是和pipeline中的代碼是想對應(yīng)的,別忘了把在settings.py中把pipeline打開。

?
1
2
3
4
5
6
7
8
9
10
item_pipelines = {
 # 'articlespider.pipelines.articlespiderpipeline': 300,
 # 'articlespider.pipelines.jsonwithencodingpipeline': 1
 
 # # 'scrapy.pipelines.images.imagepipeline': 1,
 # 'articlespider.pipelines.jsonexporterpipleline': 1
 # 'articlespider.pipelines.articleimagepipeline': 2
 # 'articlespider.pipelines.mysqlpipeline': 1
 'articlespider.pipelines.mysqltwistedpipeline': 1
}

好了,現(xiàn)在我們可以跑一程序吧。

scrapy crawl jobbole

下面是運(yùn)行結(jié)果的截圖

python使用adbapi實(shí)現(xiàn)MySQL數(shù)據(jù)庫的異步存儲

好了,以上就是今天的全部內(nèi)容了。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/Wilson_Iceman/article/details/79270235

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久99精品视频 | 天天综合7799精品影视 | 伊人91视频| 婷婷综合激情 | 精品久久国产 | 免费岛国视频 | 亚洲激情一区 | 成人黄色片网站 | 午夜网址 | 欧美亚洲高清 | 久久久久国产精品免费免费搜索 | 久久免费精品视频 | 欧美一区在线视频 | 黄色免费视频 | 欧美国产日韩一区 | 亚洲精品1| 成人黄大片视频在线观看 | 天堂va蜜桃一区二区三区漫画版 | 亚洲国产精品美女 | 成人黄色在线观看 | 伦一区二区三区中文字幕v亚洲 | 国产精品一区久久久 | 日韩手机在线 | 亚洲蜜桃精久久久久久久 | 欧美日韩在线电影 | 激情视频网| 欧美成人免费 | 91色乱码一区二区三区 | 国产欧美日韩三级 | 久久久精品一区 | 黄色成人在线 | 99久久精品国产一区二区三区 | 日韩欧美国产一区二区 | 日韩国产| 国产成人精品一区二区三区视频 | 九九热在线观看 | 久久久久久亚洲一区二区三区蜜臀 | 中文字幕亚洲一区二区三区 | 欧美亚洲日本 | 国产精品激情 | 欧美日韩视频 |