一 crawlspider
crawlspider 是scrapy提供的一个通用爬虫,crawlspider 继承了spider类,除了拥有spider类的所有方法和属性。crawlspider还拥有着自己的属性和方法
rule参数解析
二 Itemloader
我们了解了利用CrawlSpider的Rule来定义页面的爬取逻辑,这是可配置化的一部分内容。但是,Rule并没有对Item的提取方式做规则定义。对于Item的提取,我们需要借助另一个模块Item Loader来实现。Item Loader提供一种便捷的机制来帮助我们方便地提取Item。它提供的一系列API可以分析原始数据对Item进行赋值。Item提供的是保存抓取数据的容器,而Item Loader提供的是填充容器的机制。有了它,数据的提取会变得更加规则化。
itemloader 的API参数
内置processor
identity :最简单的处理,直接返回数据不做任何处理
Takefirst:TakeFirst返回列表的第一个非空值,类似extract_first()的功能,常用作Output Processor
Join:Join方法相当于字符串的join()方法,可以把列表拼合成字符串,字符串默认使用空格分隔
Compose是用给定的多个函数的组合而构造的Processor,每个输入值被传递到第一个函数,其输出再传递到第二个函数,依次类推,直到最后一个函数返回整个处理器的输出。
mapcompose:与Compose类似,MapCompose可以迭代处理一个列表输入值
SelectJms:SelectJmes可以查询JSON,传入Key,返回查询所得的Value。不过需要先安装Jmespath库才可以使用它,安装好Jmespath之后,便可以使用这个Processor了
三本节目标
爬取 中华能源网
在下面贴出代码及所属文件
universal.json
{
“spider”: “universal”,
“website”: “中华能源网”,
“type”: “能源”,
“index”: “http://www.china-nengyuan.com/”,
“settings”: {
“USER_AGENT”: “Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50”
},
“start_urls”: {
“type”: “dynamic”,
“method”: “China_energy”,
“args”: [
5,
10
]
},
“allowed_domains”: [
“www.china-nengyuan.com”
],
“rules”: “China_energy”,
“item”: {
“class”: “FormItem”,
“loader”: “China_energy”,
“attrs”: {
“title”: [
{
“method”: “xpath”,
“args”: [
“//td[@align=‘center’]/h1/text()”
]
}
],
“url”: [
{
“method”: “attr”,
“args”: [
“url”
]
}
],
“text”: [
{
“method”: “xpath”,
“args”: [
“//td[@width=‘75%’]/a//text()”
]
}
],
“inf”: [
{
“method”: “xpath”,
“args”: [
“//td[@width=‘79%’]//text()”
]
}
],
“source”: [
{
“method”: “xpath”,
“args”: [
“//td[@align=‘center’]/strong/a[@class=‘blue’]//text()”
]
}
],
"website": [
{
"method": "value",
"args": [
"中华能源网"
]
}
]
}
}
}
items.py
-- coding: utf-8 --
from scrapy import Field, Item
class FormItem(Item):
title = Field()
text = Field()
inf = Field()
source = Field()
url = Field()
website = Field()
loaders.py
from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst, Join, Compose
class FormLoader(ItemLoader):
default_output_processor = TakeFirst()
class China_energy(FormLoader):
text_out = Compose(Join(), lambda s: s.strip())//文本输出处理方法
source_out = Compose(Join(), lambda s: s.strip())//来源输出处理方法
piplines.py
-- coding: utf-8 --
import codecs,json
//这部分结合了网上提供的实例,并不是原本就有的
class scrapyuniversalPipeline(object):
“”"
将数据保存到json文件,由于文件编码问题太多,这里用codecs打开,可以避免很多编码异常问题
在类加载时候自动打开文件,制定名称、打开类型(只读),编码
重载process_item,将item写入json文件,由于json.dumps处理的是dict,所以这里要把item转为dict
为了避免编码问题,这里还要把ensure_ascii设置为false,最后将item返回回去,因为其他类可能要用到
调用spider_closed信号量,当爬虫关闭时候,关闭文件
“”"
def init(self):
self.file = codecs.open(‘first.json’, ‘w’, encoding=“utf-8”)
def process_item(self, item, spider):
lines = json.dumps(dict(item), ensure_ascii=False) + "\n"
self.file.write(lines)
return item
def spider_closed(self, spider):
self.file.close()
rules.py
//china部分是原作者写的,我写的是China_energy部分
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import Rule
rules = {
# ‘china’: (
# Rule(LinkExtractor(allow=‘article/..html’, restrict_xpaths=’//div[@id=“left_side”]//div[@class=“con_item”]’),
# callback=‘parse_item’),
# Rule(LinkExtractor(restrict_xpaths=’//div[@id=“pageStyle”]//a[contains(., “下一页”)]’))
# ),
‘China_energy’: (
Rule(LinkExtractor(allow='product/..html’,restrict_xpaths=’//table[@class =“martop”]//a[@class=“zixun f14”]’
),
callback=‘parse_item’),
Rule(LinkExtractor(restrict_xpaths=’//table[@class=“membertable_page”]//a[contains(., “下一页”)]’))
)
}
settings.py
BOT_NAME = ‘scrapyuniversal’
SPIDER_MODULES = [‘scrapyuniversal.spiders’]
NEWSPIDER_MODULE = ‘scrapyuniversal.spiders’
ROBOTSTXT_OBEY = False
ITEM_PIPELINES = {‘scrapyuniversal.pipelines.scrapyuniversalPipeline’: 300,
}
urls.py
def China_energy(start,end):
for page in range(start,end+1):
yield ‘http://www.china-nengyuan.com/product/product_tiny_1068_’ + str(page) + ‘.html’
utils.py
from os.path import realpath, dirname
import json
def get_config(name):
path = dirname(realpath(file)) + ‘/configs/’ + name + ‘.json’
with open(path, ‘r’, encoding=‘utf-8’) as f:
return json.loads(f.read())
最后写一个run.py
from scrapy.crawler import CrawlerProcess
def run():
name = sys.argv[1]
custom_settings = get_config(name)
spider = custom_settings.get(‘spider’, ‘universal’)
project_settings = get_project_settings()
settings = dict(project_settings.copy())
settings.update(custom_settings.get(‘settings’))
process = CrawlerProcess(settings)
process.crawl(spider, **{‘name’: name})
process.start()
if name == ‘main’:
run()
让爬虫跑起来 效果图
附上文件预览图
本篇文章根据崔庆才的代码改写
附上地址
Scrapy框架的使用之Scrapy通用爬虫 其中有详细的讲解
https://juejin.im/post/5b026d53518825426b277dd5#heading-8