官方文檔中入門例子還是要跑一下的,執行一遍之后,可以找出一些當前版本`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]

[TOC]
一切OK!