官方文档中入门例子还是要跑一下的,执行一遍之后,可以找出一些当前版本`V1.5`和之前版本之间的差别。我没那么醒目,所以就多执行了几遍。
一些基本的命令一直没有变,例如新建一个爬虫项目的命令是:
`scrapy startproject news_scrapy` # news_scrapy是这个爬虫项目的名称
目录如下:
news_scrapy/
scrapy.cfg # 这个暂时没用上
news_scrapy/
__init__.py
items.py # 这个有用,下表
middlewares.py # 这个暂时没用上
pipelines.py # 大型爬虫用,小爬虫可不用
settings.py # 这个暂时没用上
spiders/Wynews.py # 爬虫叫做Wynews.py
__init__.py # 这个暂时没用上
这些代码的核心取自徐阿衡的博客。里面讲了怎样从[网易新闻排行榜](http://news.163.com/rank)爬取新闻。
[TOC]
但是,这些代码并不可以在`scrapy v1.5`上运行,而且我也没找到博主用的是什么版本的`scrapy`,所以,得在博主代码的基础上,做一些修改。
[TOC]
博主在[博客](http://www.shuang0420.com/2016/06/12/%E7%88%AC%E8%99%AB%E6%80%BB%E7%BB%93-%E4%BA%8C-scrapy/)和[Github](https://github.com/Shuang0420/Crawler/tree/master/wynews)上的代码并不完全一样,所以也提供了一些线索,即核心的部分不会更改。不一样的地方有几个:
[TOC]
在`Github`上,`item.py`的代码如下:
```
import scrapy
class WynewsItem(scrapy.Item):
# 定义了一个 WynewsItem 类
category = scrapy.Field()
url = scrapy.Field()
secondary_title = scrapy.Field()
secondary_url = scrapy.Field()
pass
```
这个`WynewsItem`类,用在`spiders/Wynews.py
`代码里的`second_parse`方法里
```
def second_parse(self,response):
......
for i in page:
item = WynewsItem() # WynewsItem类用在这里
item['category'] = item_1['category'].encode('utf8')
item['url'] = item_1['url'].encode('utf8')
item['secondary_title'] = i.xpath('text()').extract_first().encode('utf8')
item['secondary_url'] = i.xpath('@href').extract_first().encode('utf8')
#print i.xpath('text()').extract(),i.xpath('@href').extract()
items.append(item)
return items
```
[TOC]
在博客里,`item.py`的代码如下:
```
import scrapy
class NewsScrapyItem(scrapy.Item):
# 定义了一个 NewsScrapyItem 类
category = scrapy.Field()
url = scrapy.Field()
secondary_title = scrapy.Field()
secondary_url = scrapy.Field()
#text = Field()
```
这个`NewsScrapyItem`类,并没有体现在`spiders/Wynews.py
`代码里的`second_parse`方法里,而是多了一个`DidiScrapyItem`类:
```
def second_parse(self,response):
......
for i in page:
item = DidiScrapyItem() # 反而多了一个DidiScrapyItem类
item['category'] = item_1['category'].encode('utf8')
item['url'] = item_1['url'].encode('utf8')
item['secondary_title'] = i.xpath('text()').extract_first().encode('utf8')
item['secondary_url'] = i.xpath('@href').extract_first().encode('utf8')
#print i.xpath('text()').extract(),i.xpath('@href').extract()
items.append(item)
return items
```
如果按照博客上的代码执行,程序会报错,找不到`DidiScrapyItem`这个类,因为程序里并没有定义这个类。
然后,按照`Github`上的代码更改后,这个报错就没有了。
[TOC]
但是在报错的道路上,问题一直存在,这些问题和博主就没关系了,因为是版本升级造成的。
问题是`spiders/Wynews.py
`代码里的`parse`和`second_parse`两个方法里,`Scrapy v1.5.1`的几个内建函数已经没有了,被整合了,如果按旧版本操作,就会报错。
`spiders/Wynews.py
`报错的位置在:
```
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import scrapy
from scrapy.spider import BaseSpider # 这里会报错
from scrapy.selector import HtmlXPathSelector # 这里会报错
from wynews.items import WynewsItem
from scrapy.http import Request # 这里会报错
class WynewsSpider(BaseSpider):
name = "Wynews"
def __init__(self, category=None, *args, **kwargs):
super(WynewsSpider, self).__init__(*args, **kwargs)
self.start_urls = ['http://news.163.com/rank/']
if category=='all':
self.category=''
else:
self.category = category
def parse(self,response):
html = HtmlXPathSelector(response) # 这里会报错
page = html.xpath('//div[@class="subNav"]/a')
......
yield Request(url=item['url'],meta={'item_1': item},callback=self.second_parse) # 这里会报错
def second_parse(self,response):
item_1= response.meta['item_1']
html = HtmlXPathSelector(response) # 这里会报错
......
return items
```
这些报错就得参考`Scrapy 1.5.1`的[官方文档](https://doc.scrapy.org/en/latest/intro/tutorial.html)了。更改后`spiders/Wynews.py
`的代码如下:
```
# -*- coding: utf-8 -*-
import scrapy
from news_scrapy.items import WynewsItem
class WynewsSpider(scrapy.Spider):
name = "Wynews"
start_urls = ['http://news.163.com/rank/']
def parse(self,response):
page = response.xpath('//div[@class="subNav"]/a')
for i in page:
item = dict()
item['category'] = i.xpath('text()').extract_first()
item['url'] = i.xpath('@href').extract_first()
print item['category'],item['url']
yield scrapy.Request(url=item['url'],meta={'item_1': item},callback=self.second_parse)
def second_parse(self,response):
item_1= response.meta['item_1']
page = response.xpath('//tr/td/a')
items = []
for i in page:
item = WynewsItem()
item['category'] = item_1['category'].encode('utf8')
item['url'] = item_1['url'].encode('utf8')
item['secondary_title'] = i.xpath('text()').extract_first().encode('utf8')
item['secondary_url'] = i.xpath('@href').extract_first().encode('utf8')
#print i.xpath('text()').extract(),i.xpath('@href').extract()
items.append(item)
return items
```
总之,新版`Scrapy 1.5.1`隐藏了很多之前版本需要显式声明的部分。我们再检查一下从[网易新闻排行榜](http://news.163.com/rank)爬取新闻爬取的效果。
`scrapy crawl Wynews -o items.json
`
[TOC]
![](https://box.kancloud.cn/7347d547788b230dc607bba5314e4057_1219x534.png)
[TOC]
一切OK!