scrapy shell是用来调试的,要写爬虫需要建一个项目
scrapy 文档地址:
http://doc.scrapy.org/en/latest/topics/loaders.html
有些类没法用的时候找找需要import哪些东西
1、建立项目
先启动虚拟机:vagrant up
如果有启动不了的情况,直接打开virtualbox启动就行,然后回到windows的cmd下登录:vagrant ssh
或者直接在virtualbox里操作虚拟机【virtualbox里登录是需要密码的,俩都是vagrant】。
然后建立一个名字是projecties的项目,发现是python2.7的。
$ scrapy startproject projecties
显示结果:
New Scrapy project 'properties', using template directory '/usr/local/lib/python2.7/dist-packages/scrapy/templates/project', created in:
/home/vagrant/properties
You can start your first spider with:
cd properties
scrapy genspider example example.com
然后我就在virtualbox里删掉了上面那个项目:rm -rf projecties
在conda里新建了一个python3的环境,激活环境后重新开始创建项目,结果如下,就是在自己建的conda环境下的python3.6的项目了
然后进入项目中
$ cd properties
查看项目列表
$ls
# 或者安装tree用tree来查看
# 安装:
$ sudo apt-get -y install tree
$ tree
其中,我们需要的是item.py,piplines.py,settings.py。
2、声明item
将item.py修改,定义各种field
from scrapy.item import Item,Field
class ProjectiesItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# primary fields
#这里根据自己要爬取的东西进行定义,刚开始我想爬取的网站有反爬虫,于是就转到没有反爬虫的网站,然后要爬取的内容是game相关,于是要在这里定义一些game的item,要不然爬出来的东西没地方放
new_game = Field()
hot_game = Field()
title = Field()
price =Field()
description = Field()
image_urls = Field()
# calculated field images = Field()
location = Field()
# keeping fields url = Field()
project = Field() spider = Field() server = Field()
date = Field()
3、爬虫编写
scrapy有一些爬虫的模板,先生成一个模板再改方便点
$ scrapy genspider basic web
#其他模板查看:
$ scrapy genspider -l
首先选取一个目标网站,最多的教程就是爬取电影广告之类的:
https://movie.douban.com/top250
然后将这个链接放到爬虫里的basic.py中,代码如下
# -*- coding: utf-8 -*-
import scrapy
class BasicSpider(scrapy.Spider):
name = 'basic'
allowed_domains = ['web']
start_urls = ['https://movie.douban.com/top250']
def parse(self, response):
self.log("move_name:%s"% response.xpath('//*[@class="title"][1]/text()').extract())
self.log("star:%s"% response.xpath('//*[@class="star"][1]/text()').extract())
self.log("quo:%s"% response.xpath('//*[@class="quote""][1]/text()').extract())
然后在basic.py的那个目录下运行
scrapy crawl basic
然后会有一堆log运行打印出来,但是豆瓣这个网站403了,所以要设置代理,这个之后再整,先重新找个别的能跑的网站看看效果。然后就爬出来一堆东西,没有进行格式调整,就那么先试试效果。
#只保留了文本信息:
import scrapy
class BasicSpider(scrapy.Spider):
name = 'basic'
allowed_domains = ['web']
start_urls = ['https://game.bilibili.com/?spm_id_from=333.851.b_696e7465726e6174696f6e616c486561646572.3']
def parse(self, response):
self.log("name : %s"% response.xpath('//*[@id="track_new_game_booking"]/dl/dd/a/text()').extract())
另外一个指令
scrapy parse --spider=basic url
这个指令也可以爬取网页内容
scrapy parse --spider=basic https://game.bilibili.com/?spm_id_from=333.851.b_696e7465726e6174696f6e616c486561646572.3
引入item里的类
先查看一下自己的item.py里的类叫啥,然后在basic.py中引入这个类
from properties.items import ProjectiesItem
然后将这个类实例化
在parse()方法中,实例化
item = ProjectiesItem()
import scrapy
from projecties.items import ProjectiesItem
class BasicSpider(scrapy.Spider):
name = 'basic'
allowed_domains = ['web']
start_urls = ['https://game.bilibili.com/?spm_id_from=333.851.b_696e7465726e6174696f6e616c486561646572.3']
def parse(self, response):
item = ProjectiesItem()
item["new_game"]=response.xpath('//*[@id="track_new_game_booking"]/dl/dd/a/text()').extract()
item["hot_game"]=response.xpath('//*[@id="track_hot_game"]/dl/dd/a/text()').extract()
return item
4、保存文件
编写完item.py、spider.py之后,运行爬虫,并输出到items.csv(这个名字随便取,格式可以保存成json、jl、csv、xml等)其中csv、xml格式可在excel里直接用
$ scrapy crawl basic -o items.csv
5、item装载器与管理字段
工具类:ItemLoader
在parse()方法更变代码。
import scrapy
from projecties.items import ProjectiesItem
from scrapy.loader import ItemLoader
class BasicSpider(scrapy.Spider):
name = 'basic'
allowed_domains = ['web']
start_urls = ['https://game.bilibili.com/?spm_id_from=333.851.b_696e7465726e6174696f6e616c486561646572.3']
def parse(self, response):
l =ItemLoader(item=ProjectiesItem(),response=response)
l.add_xpath('new_game','//*[@id="track_new_game_booking"]/dl/dd/a/text()')
l.add_xpath('hot_game','//*[@id="track_hot_game"]/dl/dd/a/text()')
return l.load_item()
6、处理器(用来处理爬取出来的内容格式,去掉空格呀啥的)
需要导入的模块
from scrapy.loader.processors import MapCompose,Join
现在加上处理器再修改parse()方法
import scrapy
from projecties.items import ProjectiesItem
from scrapy.loader import ItemLoader
from scrapy.loader.processors import MapCompose,Join
class BasicSpider(scrapy.Spider):
name = 'basic'
allowed_domains = ['web']
start_urls = ['https://game.bilibili.com/?spm_id_from=333.851.b_696e7465726e6174696f6e616c486561646572.3']
def parse(self, response):
l =ItemLoader(item=ProjectiesItem(),response=response)
l.add_xpath('new_game','//*[@id="track_new_game_booking"]/dl/dd/a/text()',MapCompose(unicode.strip))
l.add_xpath('hot_game','//*[@id="track_hot_game"]/dl/dd/a/text()')
return l.load_item()
在xpath那里加上一些操作就可以了。
7、创建contract
contract有点像测试单元,在运行的时候输入命令
scrapy check basic
在这之前,需要对parse()方法进行更改,加@
这里之后再说****************************
8、总结
根据1-7进行项目编写,代码如下,为了展示多样性我又换了一个网站http://www.tingvoa.com/
#-*- coding: utf-8 -*-
import scrapy
from projecties.items import ProjectiesItem
from scrapy.loader import ItemLoader
from scrapy.loader.processors import MapCompose,Join
import datetime
#import urlparse
import socket
class BasicSpider(scrapy.Spider):
name = 'basic'
allowed_domains = ['web']
start_urls = ['http://www.tingvoa.com/']
def parse(self, response):
"""
@url http://www.tingvoa.com/
@return items 1
@scrapes title price description address image_urls
@scrapes url project spider server date
"""
l =ItemLoader(item=ProjectiesItem(),response=response)
l.add_xpath('title_kouyu','//*[@id="hotcetdesc1"]/ul/li/a[1]/text()')
l.add_xpath('name_kouyu','//*[@id="hotcetdesc1"]/ul/li/a[2]/text()')
l.add_xpath('title_class','//*[@id="hotcetdesc2"]/ul/li/a[1]/text()')
l.add_xpath('name_class','//*[@id="hotcetdesc2"]/ul/li/a[2]/text()')
l.add_xpath('day_item','//*[@id="container"]/div[4]/div[2]/div[3]/ul/li/a/text()',MapCompose(lambda i :i.replace('-','/')))
#ADD FIELD
l.add_value('url',response.url)
l.add_value('project',self.settings.get('BOT_NAME'))
l.add_value('spider',self.name)
l.add_value('server',socket.gethostname())
l.add_value('date',datetime.datetime.now())
return l.load_item()