Scrapy爬数据并存储到mysql中
来源:互联网 发布:php极光推送原理 编辑:程序博客网 时间:2024/05/01 08:36
前言
看这篇文嘉,假设你已经:
1. 安装了Srcapy框架
2. 安装了mysql
3. import了pymysql
后面两个可以参考我的前一篇博客,请移步:Python3.x连接Pymysql
首先来说说我踩的坑
坑1
我定义好items后,下一步是要将items这个容器引入到我的spider里面。所以要在spider文件中写上这么一句话:
from scrapytest.CourseItems import CourseItem
scrapytest是我的工程名,CourseItem是我的item的类名。但是这句话在我的notebook里面死活给我报错:
No Module named "scrapytest"
What?我的scrapytest好好的在那啊。然后我建立一个同层的py文件,就是好的,所以我推测可能在notebook上面没有这种导入吧。
坑2
我最后爬的数据,根本就存储不到数据库中,所以我检查了几个步骤来排查原因:
1.到底有没有爬到数据?
我写了一个生成json文件的类,然后去看了我保存下来的json,里面是有数据的,所以是数据库插入的问题。
2.在连接“数据池“的时候出现了问题?
我在连接函数的内部打了log,结果可以打印log,所以连接数据库没问题。
3.数据库启动了没?
我重新写了一个简单的插入,用的是这里同样的代码,不过是把相对的数据改为绝对的数据。结果是可以存储的。所以得出结论,数据库人家好好的。
4.数据的问题?
由上一步的一些结论,我发现我的相对数据不行,但是改成绝对数据的话,就可以存储。所以我的数据格式有问题。我打印了我的数据,发现都是list,而且price还是list里面套着list。那么就知道是price的格式不对,导致我老是报错:(此处感谢帮我调了一天bug的orangesdk[可调戏])
说我没有送进去数据,它必须要一个数据才行。所以我追根溯源,去看price爬取的时候我写的xpath:
item['price'] = response.xpath('//div[@class="item-mod"]/div[@class="favor-pos"]/p[@class="price"]/span/text()').extract()
我想着数组里面套数组,肯定就是数据爬多了,所以得再精确地定位一下这个price。把前面的//div[@class=”item-mod”]删除:
item['price'] = response.xpath('//p[@class="price"]/span/text()').extract()
price格式好了之后,就可以插入了。
我们开始建立Srcapy项目
安装Scrapy这里就不再赘述了,然后就是执行以下命令新建一个Scrapy项目:
scrapy startproject scrapytest
【scrapy是我项目的名字,可以任意更改。】
然后就可以看到我们生成好的一个scrapy项目:
我们主要用的就是这四个文件:items、pipelines.py、settings.py、spiders下面的spider.py。先分别说说它们怎么用:
1.items.py:
定义你想要爬的东西的名字:
import scrapyclass HouseItem(scrapy.Item): #名称 name = scrapy.Field() #区域 region = scrapy.Field() #价格 price= scrapy.Field()
等号后面的scrapy.Field()是固定搭配,HouseItem是我的item的类名,其实我这个文件叫做HouseItem.py,我在item.py的同一层新建的,跟直接在item.py里面写的效果是一样的。
2.pipelines.py
pipelines里面是写其他操作类的。比如写一个类专门向数据库中插值,一个类专门生成json。向数据库中插值代码如下:
from scrapy import logimport pymysqlimport pymysql.cursorsimport codecsfrom twisted.enterprise import adbapiclass WebcrawlerScrapyPipeline(object): @classmethod def from_settings(cls, settings): dbargs = dict( host=settings['MYSQL_HOST'], db=settings['MYSQL_DBNAME'], user=settings['MYSQL_USER'], passwd=settings['MYSQL_PASSWD'], port=settings['MYSQL_PORT'], charset='utf8', cursorclass=pymysql.cursors.DictCursor, use_unicode=True, ) dbpool = adbapi.ConnectionPool('pymysql', **dbargs) return cls(dbpool) def __init__(self,dbpool): self.dbpool=dbpool #pipeline默认调用 def process_item(self, item, spider): d=self.dbpool.runInteraction(self._conditional_insert, item, spider)#调用插入的方法 log.msg("-------------------连接好了-------------------") d.addErrback(self._handle_error,item,spider)#调用异常处理方法 d.addBoth(lambda _: item) return d def _conditional_insert(self, conn, item, spider): log.msg("-------------------打印-------------------") conn.execute("insert into test (name, region, price) values(%s, %s, %s)", (item['name'], item['region'], item['price'])) log.msg("-------------------一轮循环完毕-------------------") def _handle_error(self, failue, item, spider): print(failue)
我们可以改的东西:
- 类名可以改
cursorclass=pymysql.cursors.DictCursor
里面的pymysql,是因为我用的是pymysql,如果你是python3.4以前的版本的话,你可以使用MySQLDB。dbpool = adbapi.ConnectionPool('pymysql', **dbargs)
这个里面的pymysql同上.- “_conditional_insert” 这个方法的方法名可以改,如果更改的话,上面的
d=self.dbpool.runInteraction(self._conditional_insert, item, spider)
调用的名字也要改. - “_conditional_insert” 插入的sql语句:
conn.execute("insert into test (name, region, price) values(%s, %s, %s)",(item['name'], item['region'], item['price']))
这句话一定要写对。test是表名,在执行这个操作之前,你要确保你的数据库里面有这个表。表里面的字段有你item里面的那几个字段,这些都是一一对应的。
3.settings.py
settings最重要的就是要加上两个设置:
- 引入前面你写的类,并附上优先级(后面的数字就是优先级,数字越小越优先执行)。
ITEM_PIPELINES = { 'scrapytest.MyPipelines.WebcrawlerScrapyPipeline': 300, 'scrapytest.MyPipelines.MyPipeline': 1,}
- 添加数据库信息。如果是本地的,就写上localhost,如果连接的是远程的mysql数据库,则直接写远程的ip。
MYSQL_HOST = 'localhost'MYSQL_DBNAME = 'test' #数据库名字,请修改MYSQL_USER = 'root' #数据库账号,请修改MYSQL_PASSWD = 'root' #数据库密码,请修改MYSQL_PORT = 3306 #数据库端口
4.spiders下面的spider.py
import scrapyfrom scrapytest.HouseItems import HouseItemclass MySpider(scrapy.Spider): name = "MySpider" # 设定域名 allowed_domains = ["anjuke.com"] # 填写爬取地址 start_urls = [ 'https://xa.fang.anjuke.com/loupan/all/p%s/' % p for p in range(1, 15) ] # 编写爬取方法 def parse(self, response): # 实例一个容器保存爬取的信息 item = CourseItem() # 这部分是爬取部分,使用xpath的方式选择信息,具体方法根据网页结构而定 item['name'] = response.xpath('//div[@class="infos"]/div[@class="lp-name"]/h3/a[@class="items-name"]/text()').extract() item['region'] = response.xpath('//div[@class="infos"]/p[@class="address"]/a[@class="list-map"]/text()').extract() item['price'] = response.xpath('//p[@class="price"]/span/text()').extract() yield item
需要注意:
- 一定要引入你的Items文件,如果不引入会不知道你要爬哪个,会说你下面的item都没有定义。
- 一定要写上name。这里我的name是叫“MySpider”。因为有时候可能会并行几个爬虫,名字可以用来区分。而且当你运行整个项目的时候,也是直接运行爬虫。执行的命令行需要输入名字。
- item一定要先初始化。
item = HouseItem()
。给它初始化一下,才能知道后面我们定义的都是什么。 - Xpath一定要写对。Xpath的语法网上有很多,这里不再详述,可以自行百度。(我往往出错都是Xpath没写对= =)
- Xpath后面不要忘记写.extract()。
- 最后来一个yield item一定不能忘记。yield的意思是把你获取的抛出后,继续执行这个函数。和return的区别就是会继续执行,而return不会继续。
- ## 运行我们的Srcapy项目
进入项目目录之后,执行:
Scrapy crawl MySpider
就可以在数据库中看到结果了。看不到结果的,请参照我前面写的坑2的调试方法。
memoryjdch编辑于2017.8.18
- Scrapy爬数据并存储到mysql中
- Scrapy爬数据并存储到mysql中
- scrapy爬取豆瓣电影top250并存储到mysql
- 使用Scrapy爬取笑话并存储到文件和MySQL
- python,scrapy爬虫sql之爬取数据存储到mysql的piplelines.py配置
- Scrapy+MongoDB爬取并存储豌豆荚App数据
- Scrapy爬取网页并保存到数据库中
- Python3.6实现scrapy框架爬取数据并将数据插入MySQL与存入文档中
- Spark数据存储到mysql中
- scrapy 详细实例-爬取百度贴吧数据并保存到文件和和数据库中
- Hive搭建并将元数据存储到MySQL
- Nutch Crawler抓取数据并存储到MySQL
- 爬取腾讯招聘scrapy框架实现,并以(表格,json)形式存储到本地
- MySQL字符分割并存储到临时表中
- C++中序列化对象并存储到mysql
- 图像存储到XML数据中,并读取出来
- 用Python Scrapy爬取某电影网站并存储入mysql
- Python爬虫系列之----Scrapy(八)爬取豆瓣读书某个tag下的所有书籍并保存到Mysql数据库中去
- WebSocket实现app扫描二维码登录
- 不用Mac也可以将打包好的ipa上架App
- UML过程
- 转合理配置GOMAXPROCS提升一倍以上的性能
- 2017百度之星1006小小粉丝度度熊(尺举法)
- Scrapy爬数据并存储到mysql中
- jQuery Ajax方法
- Ubuntu从待机中唤醒后鼠标键盘出现僵死情况
- Hdu 5212 Code【容斥原理】
- nexus的仓库介绍,以及配置远程仓库
- [玩转算法]滑动窗口
- intellj idea将自己常用的文件类型添加到菜单栏中
- Android跳转应用市场评分以及目前国内主要的市场包名
- spring junit 测试示例 maven 搭界