首先创建一个新的project,在cmd下执行以下命令
scrapy startproject wiki
得到一个新的project
现在新建一个spider来抓取wikipedia英文主页上的内容。使用以下命令新建一个spider文件
scrapy genspider main en.wikipedia.org
然后在编译器里打开在spiders下生成的main.py文件,可见代码如下
# -*- coding: utf-8 -*-
import scrapy
class MainSpider(scrapy.Spider):
name = "main"
allowed_domains = ["en.wikipedia.org"]
start_urls = (
'http://www.en.wikipedia.org/',
)
def parse(self, response):
pass
然后把start_urls中的url改成wikipedia主页的url:
From today's featured article
scrapy shell https://en.wikipedia.org/wiki/Main_Page
response.xpath('//h2/span/text()').extract()
这样可以得到和上述一样的结果。
scrapy crawl main --nolog
这样做之后输出结果会清爽很多。
from scrapy.item import Item, Field
class WikiItem(Item):
titles = Field()
urls = Field()
在这里定义了两个域,titles和urls,分别用于存放题目和链接地址
from scrapy.loader import ItemLoader
from wiki.items import WikiItem
import scrapy
class MainSpider(scrapy.Spider):
name = "main"
allowed_domains = ["en.wikipedia.org"]
start_urls = (
'http://en.wikipedia.org/wiki/Main_Page',
)
def parse(self, response):
l = ItemLoader(item=WikiItem, response=response)
l.add_xpath('titles', '//h2/span/text()') # get all block title
l.add_xpath('urls', '//*[@href]/@href') # get all hyperlinks
print response.xpath('//h2/span/text()').extract()
print response.xpath('//*[@href]/@href').extract()
return l.load_item()
scrapy crawl main --nolog
scrapy shell https://en.wikipedia.org/wiki/Main_Page
from scrapy.loader import ItemLoader
from wiki.items import WikiItem
import scrapy
import json
l = ItemLoader(item=WikiItem, response=response)
l.add_xpath('titles', '//h2/span/text()')
l.add_xpath('urls', '//*[@href]/@href')
(其实这就是简单复制了上述文件中的代码)
然后尝试生成一个 Item 存放 l 这个 ItemLoader 中的数据。所以我尝试了下面这行命令:
dataItem = l.load_item()
但是结果报错了,内容如下:
TypeError: 'ItemMeta' object does not support item assignment
但是既然parse中的return没有报错,是不是写一个函数return一下就能赋值了?
运行如下命令:
def loaditem(loader):
return loader.load_item()
dataItem = loaditem(l)
但是结果还是会报同样的错。看来 ItemLoader 这个类不支持直接分配新的 item。到此一个不太明白的问题是既然不能直接赋值,parse() 方法中的 return l.load_item() 也没有报错,那这个返回值到底有什么作用?
不过既然这样,那么只能声明一个WikiItem对象了。
dataItem = WikiItem()
dataItem['titles'] = response.xpath('//h2/span/text()').extract()
dataItem['urls'] = response.xpath('//*[@href]/@href').extract()
dataDict = dict(dataItem)
dataJson = json.dumps()
通过查看datajson的类型发现这是一个str,所以说相当于以json的格式encode之后用str进行存储。
用json.loads()方法就能得到原始数据:
origin = json.loads(dataJson)
file = open('data.txt', 'wb')
file.write(dataJson)
file.close()
存储到.json文件中:
fjs = open('data.json', 'wb')
fjs.write(dataJson)
fjs.close()
不过根据Scrapy的文档,我发现可以通过project中的pipeline来解决数据导出的问题
# -*- coding: utf-8 -*-
# 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 WikiPipeline(object):
def process_item(self, item, spider):
return item
class JsonWriterPipeline(object):
def __init__(self):
self.file = open('data.json', 'wb')
def process_item(self, item, spider):
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
return item
其实是在文件里增加了json的导入和一个新类:JsonWriterPipeline
# Configure item pipelines
# See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'wiki.pipelines.JsonWriterPipeline': 300,
}
然后在shell中运行一下
scrapy crawl main
果然在project目录下出现了一个名为 data.json 的文件。但是文件中并无任何内容。
# -*- coding: utf-8 -*-
#from scrapy.loader import ItemLoader
from wiki.items import WikiItem
import scrapy
#import json
class MainSpider(scrapy.Spider):
name = "main"
allowed_domains = ["en.wikipedia.org"]
start_urls = (
'http://en.wikipedia.org/wiki/Main_Page',
)
def parse(self, response):
"""
l = ItemLoader(item=WikiItem, response=response)
l.add_xpath('titles', '//h2/span/text()') # get all block title
l.add_xpath('urls', '//*[@href]/@href') # get all hyperlinks
print response.xpath('//h2/span/text()').extract()
print response.xpath('//*[@href]/@href').extract()
return l.load_item()
"""
item = WikiItem()
item['titles'] = response.xpath('//h2/span/text()').extract()
item['urls'] = response.xpath('//*[@href]/@href').extract()
print(item)
return item
scrapy crawl main