scrapy库详解

scrapy是一个完整的爬虫框架,一共有5个部分组成和2个中间部分,最主要的是一下五个部分:

  1. ENGINE
  2. SCHEDULER
  3. ITEM PIPELINES
  4. SPIDERS
  5. DOWNLOADER

用户主要编写spider和item pipelines,其余三个模块是事先写好的,不需要修改

可以通过修改downloader middleware中间键来对engine,scheduler和Downloader进行配置

scrapy通过命令行运行

1
scrapy command [options] [args]

scrapy有6个常用命令

  1. startproject:创建一个新的工程
  2. genspider:创建一个爬虫
  3. settings:获得爬虫配置信息
  4. crawl:运行一个爬虫
  5. list:列出工程中所有爬虫
  6. shell:启动url调试命令行

建立一个scrapy工程的方法

1
scrapy startproject python123demo

建立完成之后可以看到的文件夹下产生了一个名为python123的文件,进入该文件可以看到一个scrapy.cfg的文件,这是一个部署scrapy的配置文件

1
2
3
4
5
6
7
8
9
10
11
│ scrapy.cfg

└─python123demo
│ items.py
│ middlewares.py
│ pipelines.py
│ settings.py
│ __init__.py

└─spiders
__init__.py

文件树目录如下, 在windows中通过tree /F python123demo查看

使用如下命令生成名为demo的爬虫,爬取的网页为python123.io

scrapy genspider demo python123.io

产生的demo.py如下

1
2
3
4
5
6
7
8
9
10
import scrapy


class DemoSpider(scrapy.Spider):
name = 'demo'
allowed_domains = ['python123.io']
start_urls = ['http://python123.io/']

def parse(self, response):
pass

scrapy的request类里面有一下几个方法:

  1. .url:request对应的请求url地址
  2. .method:对应的请求方法,’GET’,’POST’等等
  3. .headers:字典类型的请求头
  4. .body:请求内容主体,字符串类型
  5. .meta:用户添加的扩展信息,在scrapy内部模块间传递信息使用
  6. .copy():复制该请求

Rsponse类7个常用方法:

  1. .url:response对应的url地址
  2. .status:状态码,默认是200
  3. .headers:response头部信息
  4. .body:response对应的内容信息,字符串类型
  5. .flags:一组标记
  6. request:产生Response类型对应的request对象
  7. .copy():复制该响应

实例

爬取股票数据

步骤一

1
2
3
scrapy startproject BaiduStocks
cd BaiduStocks
scrapy genspider stocks baidu.com

步骤二

修改spider文件夹下的stocks.py文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import scrapy
import re

class StocksSpider(scrapy.Spider):
name = 'stocks'
start_urls = ['http://quote.eastmoney.com/stocklist.html']

def parse(self, response):
for href in response.css('a::attr(href)').extract():
try:
stock = re.findall(r"[s][hz]\d{6}", href)[0]
url = 'https://gupiao.baidu.com/stock/' + stock + '.html'
yield scrapy.Request(url, callback=self.parse_stock)
except:
continue

def parser_stock(self,response):
infodict = {}
stockInfo = response.css('.stock-bets')
name = stockInfo.css('.bets-name').extract()[0]
keyList = stockInfo.css('dt').extract()
ValueList = stockInfo.css('dd').extract()
for i in range(len(keyList)):
key = re.findall(r'>.*</dt>',keyList[i])[0][1:-5]
try:
val = re.findall(r'\d+\.?.*</dd>',ValueList[i])[0][0:-5]
except:
val = '--'
infodict[key] = val
# infodict['股票名称'] = name
infoDict.update(
{'股票名称': re.findall('\s.*\(', name)[0].split()[0] + \
re.findall('\>.*\<', name)[0][1:-1]})
yield infodict

通过东方财富网获得stock的代码,然后同过百度股票爬取信息,其中parse和perser_stock函数都通过yield变成生成器

第三步

更改pipeline.py,用于数据处理,定义一个新的处理数据的类称为BaiduStockInfoPipeline,定义open_spider,close_spider,以及process_item三个函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class BaiduStockInfoPipeline(object):
def open_spider(self,spider):
self.f = open('BaiduStockInfo.txt','w')

def close_spider(self,spider):
self.f.close()

def process_item(self,item,spider):
try:
line = str(dict(item)) + '\n'
self.f.write(line)
except:
pass
return item

第四步

修改settings.py,把ITEM_PIPELINES里面用到的类改为自己定义的BaiduStockInfoPipeline:

1
2
3
ITEM_PIPELINES = {
'BaiduStocks.pipelines.BaiduStockInfoPipeline': 300,
}