scrapy框架知识点整理
最近闲来无事,之前都是用requests自己写爬虫脚本,突发奇想,想尝试一下使用框架会怎么样。查看了下介绍,尝试着自学了一下该框架,不是很精通,现在将学习该框架的过程中总结的一些东西记录下来,一方面是方便自己以后查看,另一方面也是希望大家批评指正,补充完善。
scrapy 基本命令的说明
新建scrapy项目
XXX代表的是你为这个项目起的名字。
scrapy startproject XXX
新建爬虫
XXX代表你为这个爬虫起的名字。 XXX.com代表你需要爬取的域名。
scrapy genspider XXX XXX.com
启动爬虫
这里的爬虫名就是上一步你自己起的名字
scrapy crawl 爬虫名
spiders文件夹中爬虫文件的一些说明
数据解析的一些说明(xpath,css)
scrapy框架的数据解析是通过selector进行的,这是一个封装好的类。使用方法如下:
book_name = response.css('a')
book_name = response.xpath('//a/text()')
这个时候的book_name是一个selector对象
[<Selector xpath='./h3/a/@title' data="It's Only the Himalayas">]
我们需要从这个对象中把**data**中我们需要的数据取出来,这时候就用到了以下方法:
extract(), get_all(), get(), extract_first(), re(), re_first()
- extract() 可以返回一个含有所有的元素结果的 list 列表 [ ],如果未获取到数据,则这个列表为空
- getall() 这个和extract()的作用差不多
- extract_first() 顾名思义,这个是获取extract()返回的列表的第一个元素
- get() 这个和extract_first()的作用差不多
- re(‘正则表达式’) 这个是返回一个与正则表达式相匹配的 list 列表。selectorList支持正则表达式
- re_first() 返回第一个元素
Pipelines.py文件的一些说明
这个文件的作用是处理数据。比如:数据清洗,数据验证,过滤重复的数据,将数据写入数据库(或者特定的文件类型(Excel))
开启ITEM_PIPELINES
Item Pipelines 是可选项目,默认是关闭的。要使用这个功能需要在setting.py文件中开启相关的开关(即将注释的代码取消注释)
ITEM_PIPELINES = {
'bookdown.pipelines.PriceConverterPipline': 300,
'bookdown.pipelines.DuplicatesPipeline': 310,
}
字典中的key是pipelines.py 中的类名,注意不要写错了,val是数值,代表执行的优先级,数值越小,优先级越高(即先执行)。
"""
去重的事例
"""
class DuplicatesPipeline:
def __init__(self):
self.book_set = set()
def process_item(self, item, spider):
name = item["name"]
if name in self.book_set:
raise scrapy.exceptions.DropItem("重复的书籍为:{}".format(item))
self.book_set.add(name)
return item
"""
数值转换的事例
"""
class PriceConverterPipline:
exchange_rate = 8.5309
def process_item(self, item, spider):
price = float(item["price"]) * self.exchange_rate
item["price"] = "¥{:.2f}".format(price)
return item
LinkExtractor的一些说明
这个类的作用是用来提取链接的,也就是url地址(类比,不准确)。
LinkExtractor的导入
from scrapy.linkextractors import LinkExtractor
"""
用法的示例
"""
le = LinkExtractor(restrict_xpaths='//ul[@class="pager"]/li[@class="next"]/a')
le = LinkExtractor(restrict_css='ul.pager li.next')
"""
上面这两个写法一个是xpath,一个是css,获取的内容是一样的
"""
links = le.extract_links(response)
"""
这是links获取的数据样式,它是一个list集合,每一个Link()都是集合中的一个元素。
可以用 linkes[0].url 获得links第一个Link的url
[Link(url='http://books.toscrape.com/catalogue/page-2.html', text='next', fragment='',
nofollow=False)]
"""
LinkExtractor()的参数说明
pattern = '/info/.+\.html$'
pattern = ['/info/.+\.html$', '/waring/.+\.html$']
le = LinkExtractor(allow=pattern)
- allow
接收一个正则表达式或者一个正则表达式列表,提取与正则表达式匹配的url,如果参数为空,则提取全部url - deny
接收一个正则表达式或者一个正则表达式列表,提取与正则表达式不匹配的url,如果参数为空,则提取全部url - all_domains
接收一个域名(baidu.com)或者域名列表[“baidu.com”, “github.com”],提取与域名匹配的链接 - deny_domains
接收一个域名(baidu.com)或者域名列表[“baidu.com”, “github.com”],提取与域名不匹配的链接 - restrict_xpaths
接收一个Xpath表达式或Xpath表达式列表,获取与Xpath表达式匹配的链接 - restrict_css
接收一个CSS选择器或CSS选择器列表,获取与CSS选择器匹配的链接 - tags
提取指定标签或标签列表([‘a’])内的链接 - attrs
提取指定属性或属性列表([‘href’, ‘src’])内的链接 - process_value
传入一个函数def,将函数的return值转换成所需要的链接。 例如真实的url隐藏在类似 <a href=“javascript:gotopage(’/example.html’); return false”> 中,通过一个函数对获取的href值"javascript:gotopage(’/example.html’); return false"进行处理后,变成’/example.html’。这时就能生成我们所需要的url了。
Exporter导出数据
内置的数据格式
- JSON(JsonItemExporter)
- JSON lines(JsonLinesItemExporter)
- CSV(CsvItemExporter)
- XML(XmlItemExporter)
- Pickle(PickleItemExporter)
- Marshal(MarshalItemExporter)
命令行的方式导出数据
- 运行scrapy crawl 命令时,使用-o(文件路径) 和 -t(数据格式) 参数指定导出数据
scrapy crawl books -o books.csv
scrapy crawl books -o books.data -t csv
再settings.py中设置导出数据
- FEED_URI设置导出数据的路径,这里有一个坑,变量的名字是uri(I),不是url(L),一定注意
"""
%(name)s 这个代表爬虫的名字
%(time)s 这个代表爬虫运行的时间
"""
FEED_URI = 'export/%(name)s/%(time)s.csv'
- FEED_FORMAT 设置导出数据的格式
FEED_FORMAT = "csv"
- FEED_EXPORT_ENCODING 设置导出数据的文件编码,一般默认为utf-8
FEED_EXPORT_ENCODING = "gbk"
- FEED_EXPORT_FIELDS 导出数据包含的字段(默认导出所有字段),并确定顺序
FEED_EXPORT_FIELDS = ["name", "modle", "age"]
- FEED_EXPORTERS 用户自定义Expoter字典,添加新的导出数据的格式
FEED_EXPORTERS = { "excel" : "my_project.my_exporters.ExcelItemExporter" }
注意,scrapy2.5版本对 FEED 做出了修改,废弃了 FEED_URI 改用 FEEDS。 FEEDS 不仅用来设置路径,格式,编码,输出字段,等都可以在FEEDS中配置。示例代码如下:
FEEDS = {
"export/%(name)s/%(time)s.xls": {
"format": "excel",
"encoding": "utf8",
"fields": ["UPC", "name", "price", "availability", "star_number", "reviews_num", "image_urls", "images"]
},
}
FilesPipeline和ImagesPipeline的配置(用来下载文件和图片)
配置步骤 1 在setting.py中配置Item Pipeline
ITEM_PIPELINES = {
'scrapy.pipelines.files.FilesPipeline' : 1,
'scrapy.pipelines.images.ImagesPipeline':2,
}
配置步骤 2 在setting.py中配置下载目录FILES_STORE
"""
这个位置按自己的实际情况自己配置哈
"""
FILES_STORE = "/home/liushuo/Download/scrapy"
IMAGES_STORE = "/home/liushuo/Download/scrapy"
配置步骤 3 在Spider解析时增加 item字段
- 处理FilesPipeline时
在Spider解析一个包含文件下载链接的页面时,将所有需要下载文件的url地址收集到一个列表,赋给item的file_urls字段(item[‘file_urls’])。FilesPipeline在处理每一项item时,会读取item[‘file_urls’],对其中每一个url进行下载。下载结果信息会在item的files字段中保存(item[“files”])。 Spider示例代码如下
class DownloadBookSpider(scrapy.Spider):
...
def parse(response):
item = {}
item['file_urls'] = []
for url in response.xpath('//a/@href').extract():
download_url = response.urljoin(url)
item['file_urls'].append(download_url)
yield item
- 处理ImagesPipeline时
在Spider解析一个包含图片下载链接的页面时,将所有需要下载图片的url地址收集到一个列表,赋给item的image_urls字段(item[‘image_urls’])。FilesPipeline在处理每一项item时,会读取item[‘image_urls’],对其中每一个url进行下载。下载结果信息会在item的images字段中保存(item[“images”])。 Spider示例代码如下
class DownloadBookSpider(scrapy.Spider):
...
def parse(response):
item = {}
item['image_urls'] = []
for url in response.xpath('//a/@href').extract():
download_url = response.urljoin(url)
item['image_urls'].append(download_url)
yield item
配置步骤 4 自定义图片或者文件的文件名(功能可选)
这个设定如果不设置,那么文件的命名规则为:SHA1 hash(哈希值)+.jpg 例如:“3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg”
更改ImagesPipeline 和 FilesPipeline文件名的办法
- 这个的办法就是重写ImagesPipeline 和 FilesPipeline 中的 def file_path(self, request, response=None, info=None, *, item=None)方法来实现
示例代码如下:
import os
from urllib.parse import urlparse
from scrapy.pipelines.files import FilesPipeline
class MyFilesPipeline(FilesPipeline):
def file_path(self, request, response=None, info=None, *, item=None):
return 'files/' + os.path.basename(urlparse(request.url).path)
"""
以下是ImagesPipeline的
"""
import os
from urllib.parse import urlparse
from scrapy.pipelines.images import ImagesPipeline
class MyImagesPipeline(ImagesPipeline):
def file_path(self, request, response=None, info=None, *, item=None):
path = urlparse(request.url).path
return 'files/' + os.path.basename(path)
- 在setting.py中修改配置,将系统自带的删除或注释掉,加入自己重写的类,示例代码如下:
ITEM_PIPELINES = {
'myproject.pipelines.MyFilesPipeline': 300,
'myproject.pipelines.MyImagesPipeline': 300
}
ImagesPipeline 特有的特性
确保pillow库已安装,版本号为4.0及以上
ImagesPipeline 依赖pillow库。依靠这个库来实现JPEG/RGB格式图片增加缩略图或者将尺寸过小的图片过滤。
开启缩略图
开启该功能,只需在配置文件settings.py中设置IMAGES_THUMBS,它是一个字典,每一项的值是缩略图的尺寸,开启该功能后,会下载3张图片,分别为原图,“small”图,"big"图。 代码如下:
IMAGES_THUMBS = {
'small': (50, 50),
'big': (270, 270),
}
过滤尺寸过小的图片
开启该功能,只需在配置文件settings.py中设置IMAGES_MIN_WIDTH和IMAGES_MIN_HEIGHT,它们分别指定图片最小的宽和高。开启该功能后,只要宽和高有一项不符合设定,图片就会被舍弃。如100×210的图片,因为105不符合设定,该图片就会被舍弃。 代码如下:
IMAGES_MIN_WIDTH = 110
IMAGES_MIN_HEIGHT = 110
|