scrapy爬取到的数据如何写入MySQL

在抓取伯乐在线上面的文章的信息的时候我们尝试将抓取到的数据写入数据库。

写入的方式有两种,一种是同步的写入,另一种是异步的写入。

同步的写入比较好理解,就是爬到数据以后就立刻将数据写入MySQL。

但是同步地写入有一个缺点,因为scrapy爬取数据的速度远远大于将数据写入MySQL的速度,在数据量比较小的时候造成的影响不大,但是当数据量非常大的时候就会出现很多的问题。所以我们要采用异步的方式爬取数据并且写入MySQL。

python有一个Twisted框架可以完成异步的写入。这个框架可以提供一个连接池,先将爬取到的数据缓存进连接池,然后将连接池中的数据写入MySQL。

举个例子:pipeline.py文件:

首先是同步写入数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 链接数据库,将爬取道德内容存储到数据库中
class MysqlPipeline(object):
def __init__(self):
# 首先要连接数据库,connect()的参数分别是root, user_name, mysql pwd, datebase_name. 字符集,以及是否使用Unicode编码
self.conn = MySQLdb.connect('localhost', 'root', '123456', 'article_spider', charset='utf8', use_unicode=True)
self.cursor = self.conn.cursor()
def process_item(self,item, spider):
# 在sql语句中,"%s"是占位符,用来占住位置,方便接下来传参数
insert_sql = """
insert into jobbolearticle(title, post_date, url, favor_num,
comments_num, praise_num, tags,url_object_id, front_image_url, contant)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s,%s)
"""
self.cursor.execute(insert_sql, (item["title"], item["post_date"], item["url"],
item["favor_num"], item["comments_num"],
item["praise_num"],item["tags"],item["url_object_id"],
item["front_image_url"][0], item["contant"]))
# 为什么最后要commit呢?这里有一个坑,一开始写成了cursor.commit,但是出错了,改成conn试一试。
self.conn.commit()

初始化的时候先连接数据库,完成连接以后,填写process_item函数体,里面包括要执行的sql语句,在执行execute()执行这个语句,并且将item里面的数据写入数据库,最后commit,虽然我不知道commit有什么用。


接下来是异步的方式:

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
import MySQLdb.cursors
from twisted.enterprise import adbapi
...
# 使用Twist框架提供的连接池将数据插入MySQL
class MtSQLTwistedPipeline(object):
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 = 'utf-8',
cursorclass = MySQLdb.cursors.DictCursor,
use_unicode = True,
)
dbpool = adbapi.ConnectionPool("MySQLdb", **dbparms)
return cls(dbpool)
# 使用Twisted将MySQL插入变成异步执行
def process_item(self, item, spider):
query = self.dbpool.runInteraction(self.do_insert, item)
# 在执行期间可能会出现错误,但是因为是异步的,所以不能等错误返回再处理错误。
query.addErrback(self.handle_error, item, spider)
# 处理异步插入的异常
def handle_error(self, failure, item, spider):
print(failure)
# 执行具体的插入
def do_insert(self, cursor, item):
# 在sql语句中,"%s"是占位符,用来占住位置,方便接下来传参数
insert_sql = """
insert into jobbolearticle(title, post_date, url, favor_num,
comments_num, praise_num, tags,url_object_id, front_image_url, contant)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s,%s)
"""
cursor.execute(insert_sql, (item["title"], item["post_date"], item["url"],
item["favor_num"], item["comments_num"],
item["praise_num"],item["tags"],item["url_object_id"],
item["front_image_url"][0], item["contant"]))

这个写法基本是固定的,我们如果做修改,也是修改sql语句,以及出传递的item