scrapy 整合 djangoitem,摆脱保存数据时SQL报错的困扰
这里有一个官方的链接,虽然说的并不完整,但是思路讲解的还是很不错的:https://pypi.python.org/pypi/scrapy-djangoitem/1.1.1
这里我做了一个小案例,会一步步从头进行整合,再次熟悉整个流程。为了达到更好的效果,有些变量名包含近似的含义,方便理解思路,而有的变量名完全没有意义,便于展示不同类与方法之间的指向关系。
这篇博客从以下几个部分阐述:
- 基本环境安装
- 思路简介
- 在django上的操作
- 在scrapy上的操作
- 案例源码
一 基本环境安装
我是ubuntu17.04,python3.5的实验环境
- pip install django
- pip install scrapy
- pip install pymysql#用来连接mysql数据库python2中为mysqldb,python3中是pymysql
- pip install mysqlclient
- pip install scrapy_djangoitem # 用来连接django与scrapy
二 思路简介
爬虫的核心还是要靠scrapy,因此django只是提供一个保存数据库的方法(django中叫做model),所以我们需要做的就是:
- 在django上搭建一个model,让所有需要保存的数据通过这个model,依靠django框架完成保存
- 在scrapy上写一个爬虫,得到数据源,然后传递到这个model中
三 在django上的操作
确保环境搭建需要安装的模块都安装完毕后继续进行 ~
这里建议新建一个空文件夹,方便一步步熟悉整个流程。这里我新建了一个空文件夹:scrapy_django_testPro
1.在命令行中cd到这个空文件下,然后:
django-admin startproject mydjango
如果是pycharm的编辑器,把最外面的mydjango标记为资源文件:(右键,下面有一个mark directory as 然后选source root)
这样就新建了一个django的项目,名字是mydjango 。总的来数在django上只需要完成两部操作:配置在mysql中保存的位置,还有新建一个model
2.配置mysql
在这个位置找到settings.py文件,打开:
然后找到这段话:
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': os.path.join(BASE_DIR, 'db.sqlite3'),}
}
替换掉,具体的配置根据自己的情况来:
DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql', # 使用mysql进行数据存储'NAME': 'scrapy_django_testPro', # 数据库的名称'USER': 'root', # 用户名'PASSWORD': 'rootpwd', # 密码'HOST': '127.0.0.1', # 数据库地址'PORT': '3306' # 端口}
}
完成度django部分 50 %
3.新建model
想要新建model,需要先建立一个app,然后依靠app来建model:
》新建 app
1.首先进入这个项目中:
cd mydjango/
然后建立app:为了便于区分,我叫它 save_app,用以表示是做存储的app:
python manage.py startapp save_app
2.在刚才的setting文件中找到这一栏:
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',
]
在这里面添加上咱们的app,修改为:
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','save_app',
]
》新建model:
1.打开save_app的文件夹,打开models.py文件
添加如下代码:
class My_save_model(models.Model):con1 = models.CharField(max_length=255)con2 = models.CharField(max_length=255)
之后的数据交给model就好,它会在django的框架中找到mysql的配置,进行保存。
2.在当前目录(目录文件中包含有manage.py)的命令行中,输入如下命令:
python manage.py makemigrations
python manage.py migrate
这时,可以通过mysql可视化的工具看到这里多了N张表,但是最重要的是这里有一张表,叫做:save_app_my_save_model(django的数据表会自动命名为:app名_model名)
完成这步,django这部分就结束了,之后就是scrapy的操作了。
四 在scrapy上的操作
scrapy上总的来说有五步:
- item.py编写,把django中的models延伸到scrapy中来
- pipeline.py编写,告诉django保存item中的数据
- settings.py配置,使整个“后勤”生效
- 爬虫类编写,获取数据源
- 使我们可以在编辑器中调试这个整合过的项目
实际编写的逻辑和爬虫真正执行的逻辑是反着来的。
1.item.py的编写
首先我们需要先建立一个爬虫项目,将命令行所在的位置移动到scrapy_django_testPro 这个根目录下,执行下面的命令就可以了:
cd .. # 返回上一级目录
scrapy startproject myscrapy # 创建爬虫项目,名字是:myscrapy
然后把最外层的myscrapy标记为sourc root(如果是pycharm)
连续点开两个myscrapy文件后,我们可以看到这样子的目录:
点开这个items.py文件,可以看到有一个MyscrapyItem的模板
我们修改这个模板,为:
from scrapy_djangoitem import DjangoItem
from save_app.models import My_save_modelclass MyscrapyItem(DjangoItem):django_model = My_save_model # 注意这里不要有小括号,因为我们不是调用方法,而只是单纯的把函数名传递过去
这里,我们更换了继承的类,同时通过这个scrapy的items.py导入了django中的app的model,完成了两个框架间的关联
2.pipeline.py编写,告诉django保存item中的数据
只需要添加一句话就行,在原有的MyscrapyPipeline的基础上改为:
class MyscrapyPipeline(object):def process_item(self, item, spider):item.save()return item
这样就可以了,这个pipeline会在一组数据都有序的填充到item之后得到执行,执行save()方法就可以加入到mysql中了。
3.settings.py配置,使整个“后勤”生效
》第一个:
ROBOTSTXT_OBEY = False # 默认会是True,自信的改了它,hahaha
》第二个:默认会被注释掉,只需要取消注释即可
ITEM_PIPELINES = {'myscrapy.pipelines.MyscrapyPipeline': 300,
}
》在最上方添加环境变量:
import sys
import os
import djangoBASE_DIR = os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
PRO_ROOT = os.path.dirname(BASE_DIR) # 两个项目共同的根目录sys.path.append(os.path.join(PRO_ROOT, 'myscrapy'))
sys.path.append(os.path.join(BASE_DIR, 'myscrapy'))
os.environ['DJANGO_SETTINGS_MODULE'] = 'mydjango.settings'
django.setup()
4.爬虫类编写,获取数据源
这里我使用网上down来的:
在spiders文件夹下新建Myspider文件,然后粘贴下面的爬虫代码
import scrapy
from myscrapy.items import MyscrapyItemclass Myspider(scrapy.Spider):name = "myspider_haha"start_urls = ['http://quotes.toscrape.com/tag/humor/',]def parse(self, response):for quote in response.css('div.quote'):item = MyscrapyItem()item['con1'] = quote.css('span.text::text').extract_first()item['con2'] = quote.xpath('span/small/text()').extract_first()yield item # 从这里发送出去的 item next_page = response.css('li.next a::attr("href")').extract_first()if next_page is not None:next_page = response.urljoin(next_page)yield scrapy.Request(next_page, callback=self.parse)
5.使我们可以在编辑器中调试这个整合过的项目
需要新建一个main.py文件,注意下图的位置:
注意图中的位置,新建一个main.py文件,添加如下代码:
import sys
import os
from scrapy.cmdline import executesys.path.append(os.path.dirname(os.path.abspath(__file__)))
execute(["scrapy", "crawl", "myspider_haha"]) # 这句代码会执行爬虫类中 name = "myspider_haha"的类
然后在代码中哪里不懂的地方加上断点,对着这个类右键调试运行,就OK了
五 案例源码:
我已经推到github上了:
https://github.com/demeen68/scrapy_django_testPro
scrapy 整合 djangoitem,摆脱保存数据时SQL报错的困扰相关推荐
- 关于PostgreSQL 插入数据时经常报错:no partition of relation found for row “tableName“ found for row (exec14 10
关于PostgreSQL 插入数据时经常报错: Caused by: com.seaboxsql.util.PSQLException: ERROR: no partition of relation ...
- Chrome插件请求数据时 请求报错(blocked:mixed-content)
Chrome插件请求数据时请求报错(blocked:mixed-content) 问题原因 解决方案 方案1:配置https 方案1:使用background.js请求http 问题原因 问题原因是我 ...
- Python连接mysql,插入数据时不报错,但是没有插入进去
Python连接mysql,插入数据时不报错,但是没有插入进去在connect方法中,设置 autocommit =True conn=pymysql.connect(host=host_db,use ...
- batocera游戏整合包_安装游戏时电脑报错?提示XXX文件缺失?一个软件完美解决...
文中所包含软件的下载方式在评论区. 适用场景:如下图,运行软件或者游戏时弹出错误提示,提示XXX缺失. 报错原因:电脑缺少软件或游戏运行所必须的运行库(Runtime),这在windows用户中很常见 ...
- Android 请求数据时,报错 HttpException:HTTP 503 Service Temporarily Unavailable”
(1)场景 http请求数据时,报以下异常 : 同时,后台也检测不到接口请求的痕迹,但是有时再试一下又行了. (2)解决思路 ①后台连接数量可能限制,比如1s内同一个人只能请求一次等,或者排查一下有 ...
- php微信昵称保存,分析一次写入微信昵称数据执行sql报错问题
客户反馈之前做的一个专题,有个用户报名数据没有正确写入.简单介绍下h5功能,类似报名功能,微信下授权后获取到openid.nichname,之后填写姓名并选择所在城市等信息,提交表单信息.其他用户填写 ...
- mysql 存储数据时,报错Cause: java.sql.SQLException: Incorrect string value: '\xF4\x80\xB3\x81\xE8\xAE...'
问题:Cause: java.sql.SQLException: Incorrect string value: '\xF4\x80\xB3\x81\xE8\xAE...' ? 解决办法:utf-8 ...
- django mysql save_python,django,向mysql更新数据时save()报错不能用
用户提问 求大神帮忙,models.py中有个Student类,当我用s = Student(...)创建对象,然后s.save()可以往mysql中插入记录,但是当我用 s.name = 'aaa' ...
- oracle 31640,导数据时ora-31640报错
单实例数据库10.2.0.4,目标数据库11.2.0.3 rac,目标准备将单实例上的数据导入到rac数据库. 在导入过程中报错如下: Processing object type SCHEMA_EX ...
最新文章
- 视觉惯性SLAM:VINS-Mono
- 史玉柱:10个企业管理智慧,成功的企业都这么做
- windows系统中常见的环境变量有哪些
- java图像处理,拷贝图像EXIF信息
- 用户日志留存所采用的技术手段
- A. [2021.1.29多校省选模拟11]最大公约数(杜教筛/数论)
- axis2 wsdl2java 报错_解决webService+axis2生成的wsdl文件有两个Bindings/Endpoint 的问题
- oracle resetlog与noresetlog的作用(转载)
- 19【推荐系统10】从POLY2、FM到FFM——自动特征交叉的解决方案
- 软件基本功:避免难度写法,代码简单易懂才是高手
- 【小教程】steam长展柜制作
- iredmail mysql 配置_Iredmail各大组件连接Mysql配置说明
- Prince和学生们侃侃而谈系列01
- 访问网络共享找不到网络名的解决方案
- vim autoformat php,vim - 如何在VI中整理HTML文件的缩进?
- java ctr_分组密码_计数器(CTR)模式_原理及java实现
- IDEA自定义注释模板实现方法。
- 安卓开发app版本更新
- 《机器学习实战》6.支持向量机(SVM)
- 关于苹果支付ApplePay的一些个人总结
热门文章
- iso安装器_U盘安装优麒麟20.04系统,Ubuntu通用
- 独立游戏[永夜仙境]4人团虚幻4开发经验
- 利用StringUtils可以避免空指针问题
- 解决:虚拟机能ping通主机,主机ping不通虚拟机
- libevent备忘
- Web服务生存周期内发生的事件/Soap扩展的阶段/Soap扩展的步骤
- 架构师要了解那些??
- 计算机辅助开始于计算机发展的第几个阶段,计算机辅助开始于计算机发展第几阶段...
- arduino char*转string_面试官:String长度有限制吗?是多少?还好我看过
- 模拟组合键 postmessage ctrl+v_《模拟江湖》:TapTap热门榜单第一,测试版评分8.0的汉家松鼠工作室新作...