1. 安装scrapy模块
1. pip install wheel 安装这个模块是为安装twisted做准备, 因为安装twisted需要用到wheel 2. 下载twisted, 因为scrapy是基于twisted的异步非阻塞框架 https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 下载和python版本, 操作系统位数对应 3. 安装twisted, 进入到下载的目录 pip install twisted 4. pip install pywin32 5. pip install scrapy
2. 创建一个scrapy项目
在终端中执行下面命令创建一个scrapy项目
D:OneDrive - hk sar baomin incPythonprojectReptileday06>scrapy startproject testDemo New Scrapy project 'testDemo', using template directory 'c:\python36\lib\site-packages\scrapy\templates\project', created in: D:OneDrive - hk sar baomin incPythonprojectReptileday06 estDemo You can start your first spider with: cd testDemo scrapy genspider example example.com
3. 创建一个scrapy爬虫
cd testDemo
D:OneDrive - hk sar baomin incPythonprojectReptileday06 estDemo>scrapy genspider test www.baidu.com Created spider 'test' using template 'basic' in module: testDemo.spiders.test
4. scrapy框架的目录结构
scrapy.cfg │ └─testDemo │ items.py # item对象, 用于数据持久化数据传递 │ middlewares.py # 中间件文件 │ pipelines.py # 管道文件 │ settings.py # 配置文件 │ __init__.py │ ├─spiders #具体的爬虫文件目录 │ │ test.py # 这是刚创建的爬虫文件 │ │ __init__.py │ │ │ └─__pycache__ │ __init__.cpython-36.pyc │ └─__pycache__ settings.cpython-36.pyc __init__.cpython-36.pyc
5. 爬虫文件
# -*- coding: utf-8 -*- import scrapy class TestSpider(scrapy.Spider): name = 'test' # 爬虫文件名称 allowed_domains = ['www.baidu.com'] # 允许爬取的域名 start_urls = ['http://www.baidu.com/'] # 起始URL列表 def parse(self, response): """ 用于解析请求后得到的数据 :param response: 服务器响应的数据 :return: item对象, 用于持久化存储 """ # response.text # 获取响应的字符串 # response.url # 请求的URL # response.xpath() # 使用xpath对数据进行解析 # response.meta # 用作请求传参, time_out, proxy等参数都会放在这里 pass
6. scrapy数据持久化
在scrapy中对数据进行持久化存储需要用到item, 因为管道中只能对item对象进行持久化存储, 所以要先创建item类
然后实例化item对象, 将要持久化的数据封装到item对象中, 然后将item返回出来
item类
import scrapy class TestdemoItem(scrapy.Item): """ 这个类的作用有点类似于django的model模型类 """ content = scrapy.Field() # 要在item对象中封装的数据
爬虫文件
import scrapy from testDemo.items import TestdemoItem # 导入item类 class TestSpider(scrapy.Spider): name = 'test' # 爬虫文件名称 allowed_domains = ['www.baidu.com'] # 允许爬取的域名 start_urls = ['http://www.baidu.com/'] # 起始URL列表 def parse(self, response): content = response.xpath('//div[@class="content"]/text()').extract_first() item = TestdemoItem() # 实例化item对象 item["content"] = content # 将数据封装到item对象中 yield item # 将item对象返回出去
管道文件
class TestdemoPipeline(object): def open_spider(self, spider): """ 在爬虫程序启动的时候会调用这个函数 可以在这里进行数据库的连接等 :param spider: :return: """ pass def process_item(self, item, spider): """ 这里由来处理item对象, 对数据进行持久化操作 :param item: 爬虫文件yield的item对象 :param spider: 爬虫类对象 :return: """ with open("./text.log", mode="w", encoding="utf-8") as f: f.write(item["content"]) return item # 将item对象返回出去, 因为在配置文件中可能还有其他的管道类需要对数据进行持久化 def close_spider(self, spider): """ 爬虫程序执行完毕后, 会调用这个函数 可以在可以进行断开数据库连接等归还系统资源等操作 :param spider: :return: """ pass
关于数据持久化的配置
# 关于管道的配置 # 可以配置多个, # {管道类的路径: 该管道类的执行优先级} ITEM_PIPELINES = { 'testDemo.pipelines.TestdemoPipeline': 300, }
7. 启动爬虫程序
scrapy crawl text --nolog # --nolog: 不输出日志信息
8. scrapy手动发送请求
现在使用scrapy进行数据的爬取, 发现自己并没有发送get, post等请求, 只是指定了URL, 然后对数据进行解析, 然后将数据持久化
但是在有些时候是需要发送额外的请求才能获取到数据, 比如, 爬取图片的时候, get请求获取到图片列表, 但是这些图片都是一些小图
想要爬取到大图就需要再次发送请求, 才能获取到大图的连接
还有就是在处理分页的时候, 需要重新发送请求来获取下一页的数据
手动发送get请求
def parse(self, response): scrapy.Request(url="http://www.baidu,com", callback=self.parse) # 发送get请求
手动发送post请求
class PostSpider(scrapy.Spider): name = 'post' # allowed_domains = ['www.xxx.com'] start_urls = ['https://fanyi.baidu.com/sug'] def start_requests(self): """ 重写父类的方法, 原本这个方式是发送get请求的, 现在重写后就变成了发送post请求了 :return: """ for url in self.start_urls: yield scrapy.FormRequest(url=url, callback=self.parse, formdata=self.data()) # 使用scrapy发送post请求, 注意使用yield def parse(self, response): print(json.loads(response.text)) # response.text获取响应对象内容 def data(self): form_data = { "kw": "cat" } return form_data
6. scrapy运行流程(核心组件)
7. scrapy请求传参的用途
scrapy日志相关配置
8. 如何提升scrapy的爬取效率
9. 基于UA池和ip代理池爬取数据