尽管介绍scrapy的博文什么的都比较多,然而基本千篇一律,确实不好找到自己想要的,摸索了一天摸出了些头绪,下面我会把遇到的问题贴出来,并简单摸索下常见错误。
scrapy 安装完之后,有个bug大家应该会遇到,就是找不到_win32stdio,可以在(http://www.ppvke.com/Answer/question/26221) 下载zip文件进行解压,然后存放在python或者anaconda等的 …\Lib\site-packages\twisted\internet 目录下。
python3版本的scrapy模块跟python2有较大的区别,类结构不同,比如已经没有Basespider类了。
这里还是以爬取ppvke课堂信息为例子。
图1
首先对上图的items.py进行编辑(我用的是python编辑器),添加一些代码,代码如下:
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html
# 目录下的item.py文件
import scrapy
class PpvkeItem(scrapy.Item):
teachers = scrapy.Field()
courses = scrapy.Field()
timespan = scrapy.Field()
number = scrapy.Field()
''' 四个要爬取的项定义好了'''
再进入图一的spiders文件夹,创建自己的spider再编辑 , 或者编辑后保存在该文件夹内。我创建的是myspiders.
代码;
import scrapy
from ppvke.items import PpvkeItem
class daxiong_spider(scrapy.Spider):
name='ppvke' ''' # 爬虫的名字,用来识别爬虫的,爬虫不是文件名识别,所以
运行的时候是scrapy crawl ppvke而不是 scrapy crawl myspiders '''
allowed_domains = ['ppvke.com'] #允许域名,只能抓该域名列表范围东西
urls = [('http://www.ppvke.com/class/select?topicid=&job=1&grade=&page=&page='+str(i)) for i in range(1,6)]
start_urls =urls
def parse(self,response):#parse函数,对Spider.parse重写
item = PpvkeItem()
item['teachers'] = response.xpath('/html/body/div[2]/div[1]/div[2]/div[2]/ul/li/p[2]/text()').extract()
item['courses'] = response.xpath('/html/body/div[2]/div[1]/div[2]/div[2]/ul/li/h3/a/text()').extract()
item['number'] = response.xpath('/html/body/div[2]/div[1]/div[2]/div[2]/ul/li/p[1]/span/text()').extract()
item['timespan'] = response.xpath('/html/body/div[2]/div[1]/div[2]/div[2]/ul/li/p[1]/text()').extract()
yield item
管道,setting就不进行编辑了。
发现运行局部出错
由一个url请求返回的数据,处理时出现转码出问题
生成csv文件看 scrapy crawl ppvke -o item.csv
生成的结果是:
明显的看到B3格里面数据是列表,3,5,7,9行分别是不同的url里面抓取的值。出现转码问题的直接被scrapy丢掉了。
做些改变来简单了解scrapy怎么运行的!!!
settings.py文件中添加了
ITEM_PIPELINES={'ppvke.pipelines.PpvkePipeline':1000} python3的参数是字典型不再是lists。
把myspiders.py最后一句的yield item 返回item生成器,改成return item 返回item的值运行下,结果没有区别。
参照官方例子对pipelines.py做改动
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
import json
class PpvkePipeline(object):
def __init__(self):
self.file = open('items1.csv', 'w')
def process_item(self, item, spider):
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
return item
再运行
5行全出来了,然而都是unicode码
我有强迫症的样子,看到open()就喜欢接着close().
class PpvkePipeline(object):
def __init__(self):
self.file = open('items1.csv', 'w')
def process_item(self, item, spider):
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
self.file.close() #多了这行
return item
我发现最后结果只有一行,原因是“在一个已经关闭的文件中 进行输入输出操作”。也就是说,类PpvkePipeline只初始化(__init__)了一次,而类里面的函数process_item()被调用了5次。
最后给个结论,简单的爬虫就不要搞管道什么的,出错误反而导致数据不完全,
还不如直接在cmd上用 -o filename.filetype让它默认输出在你cd进入的目录下—-可以输出json,csv等文件。
立马把刚才在settings.py文件改的参数擦掉算了:
ITEM_PIPELINES={'ppvke.pipelines.PpvkePipeline':1000}
不过这样也不是万事大吉,上面就遇到转码问题,导致数据缺失,但是至少比错误代码安全。
不了解parse()是Spider类函数之前,总感觉一个parse函数用来返回item有点不顺手,总想着可不可以增加一个parse,比如parse1(self ,response),然而并没有用,程序报错。不过parse可以返回调用其他函数的生成器–yield Request(goten_new_url,call.back=self.function).
scrapy的框架是下图
然而我也看不出什么,downloader,internet,scrapy,scheduler并不是我们初学者需要关心的。