参考文档→scrapy docs
结构 | 内容 | 编辑 |
---|---|---|
scrapy engine | 用来处理整个系统的数据流处理, 触发事务(框架核心) | |
scheduler | 用来接受引擎发过来的request, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址 | |
downloader | 下载引擎发来的request,并返回给引擎 | |
spider | 处理引擎传来的数据,比如存储 | |
item pipeline | 处理引擎传来的数据,比如存储 | |
middlewares | 自定义下载扩展 | |
middlewarespider | 自定义requests请求和进行response过滤 |
目标:对国家信息安全漏洞库漏洞名称包含kernel的前十页相关数据。
1.准备工作
pip install scrapy
pip install pywin32
运行scrapy出现No module named 'win32api’的错误则是windows下python没有自带访问Windows系统api的库的,需要下个win32api。
然后创建一个scrapy项目为tutorial:
scrapy startproject tutorial
语法: scrapy startproject <project_name> (为全局命令)
tutorial的目录如下:
tutorial/
scrapy.cfg
tutorial/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
...
在当前spiders中创建loudong.py文件:
scrapy genspider loudong www.cnnvd.org.cn
scrapy genspider [-t template] (为项目命令,必须在项目中执行)
初始spider文件框架为:
# -*- coding: utf-8 -*-
import scrapy
class LoudongSpider(scrapy.Spider):
name = 'loudong'
allowed_domains = ['www.cnnvd.org.cn']
start_urls = ['http://www.cnnvd.org.cn/']
def parse(self, response):
pass
2.开始编辑
①编辑items.py
打开items.py,创建一个scrapy.Item
类,并定义类型为scrapy.Field
的类属性来定义每一个item,此处可以了解一下ORM,定义所需要获取的信息的名字:
class TutorialItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
name1 = scrapy.Field()
name2 = scrapy.Field()
name3 = scrapy.Field()
②编辑settings.py
打开setting.py,改成以下:
ROBOTSTXT_OBEY = False
③编辑spiders/loudong.py
开头加上将items中内容导入。
import scrapy
from scrapy.http import Request
from tutorial.items import TutorialItem
然后创建一个start_requests
的函数:
该方法必须返回一个可迭代对象(iterable)。该对象包含了spider用于爬取的第一个Request。
当spider启动爬取并且未制定URL时,该方法被调用。 当指定了URL时,make_requests_from_url() 将被调用来创建Request对象。 该方法仅仅会被Scrapy调用一次,因此您可以将其实现为生成器。
该方法的默认实现是使用 start_urls 的url生成Request
start_requests
函数用来进行网页的迭代,范围是所搜索的前十页:
点击搜索后F12查看得到:
查看Headers:
于是start_requests
部分构造如下:
def start_requests(self):
for i in range(1,19):
yield scrapy.FormRequest(
url = 'http://www.cnnvd.org.cn/web/wz/czsjlf0_01.tag?pageno=%s'%(i),
formdata = {
'cvCname' : 'router'
}
)
创建parse(response)
函数:
当response没有指定回调函数时,该方法是Scrapy处理下载的response的默认方法。
parse 负责处理response并返回处理的数据以及(/或)跟进的URL。 Spider 对其他的Request的回调函数也有相同的要求。
该方法及其他的Request回调函数必须返回一个包含 Request 及(或) Item 的可迭代的对象。
参数: response (Response) – 用于分析的response`
def parse(self, response):
url_start = 'http://www.cnnvd.org.cn'
aaa = response.xpath('//div[@class="form_style m_t_20"]')
bbb = aaa.xpath('//a[@class="a_title2"]')
for i in bbb:
url_end = i.xpath('@href').extract()[0]
next_url = "%s%s"%(url_start,url_end)
yield Request(next_url, callback=self.next)
根据自己需要提取的信息对其用Xpath表达式进行分析:
/html/head/title: 选择HTML文档中 标签内的<title> 元素
/html/head/title/text(): 选择上面提到的 <title> 元素的文字
//td: 选择所有的<td> 元素
//div[@class=“mine”]: 选择所有具有 class=“mine” 属性的 div 元素
用next(self,response)函数表示,得到以下:
def next(self,response):
self.item = TutorialItem()
aaa = response.xpath('//div[@class="detail_xq w770"]')
self.item['name'] = aaa[0].xpath('h2/text()')[0].extract()
self.item['cnnid'] = aaa[0].xpath('.//ul//span/text()')[0].extract()
self.item['cveid'] = aaa[0].xpath('.//ul//a/text()')[2].extract().strip()
yield self.item