1、安装
安装scrapy命令:
pip install scrapy==2.5.1 (pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scrapy==2.5.1) pip install scrapy-redis==0.7.2
如果安装失败. 请先升级一下pip. 然后重新安装scrapy即可.
最新版本的pip升级完成后. 安装依然失败, 可以根据报错信息进行一点点的调整, 多试几次pip. 直至success.
2、备用安装方式
如果上述过程还是无法正常安装scrapy, 可以考虑用下面的方案来安装:
-
安装wheel
pip install wheel
-
下载twisted安装包, https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
-
用wheel安装twisted.
pip install Twisted‑21.7.0‑py3‑none‑any.whl
-
安装pywin32
pip install pywin32
-
安装scrapy
pip install scrapy
总之, 最终你的控制台输入scrapy version
能显示版本号. 就算成功了
3、创建scrapy项目
创建scrapy项目的命令:scrapy startproject +<项目名字>
示例:scrapy startproject myspider
scrapy的核心组件
-
引擎(Scrapy) 用来处理整个系统的数据流处理, 触发事务(框架核心)
-
调度器(Scheduler) 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
-
下载器(Downloader) 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
-
爬虫(Spiders) 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
-
项目管道(Pipeline) 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
4、创建爬虫
命令:在项目路径下执行:scrapy genspider +<爬虫名字> + <允许爬取的域名>
示例:
-
scrapy startproject duanzi01
-
cd duanzi01/
-
scrapy genspider duanzi duanzixing.com
生成的目录和文件结果如下:
5、完善spider
完善spider即通过方法进行数据的提取等操作
在/duanzi01/duanzi01/spiders/duanzi.py中修改内容如下:
import scrapy # 自定义spider类,继承scrapy.spider class DuanziSpider(scrapy.Spider): # 爬虫名字 name = 'duanzi' # 允许爬取的范围,防止爬虫爬到别的网站 allowed_domains = ['duanzixing.com'] # 开始爬取的url地址 start_urls = ['http://duanzixing.com/'] # 数据提取的方法,接受下载中间件传过来的response 是重写父类中的parse方法 def parse(self, response, **kwargs): # 打印抓取到的页面源码 # print(response.text) # xpath匹配每条段子的article列表 article_list = response.xpath('//article[@class="excerpt"]') # print(article_list) # 循环获取每一个article for article in article_list: # 匹配标题 # title = article.xpath('./header/h2/a/text()') # [<Selector xpath='./header/h2/a/text()' data='一个不小心就把2000块钱的包包设置成了50包邮'>] # title = article.xpath('./header/h2/a/text()')[0].extract() # 等同于 title = article.xpath('./header/h2/a/text()').extract_first() # 获取段子内容 con = article.xpath('./p[@class="note"]/text()').extract_first() print('title', title) print('con', con)
启动爬虫命令: scrapy crawl duanzi
response响应对象的常用属性
-
response.url:当前响应的url地址
-
response.request.url:当前响应对应的请求的url地址
-
response.headers:响应头
-
response.request.headers:当前响应的请求头
-
response.body:响应体,也就是html代码,byte类型
-
response.text 返回响应的内容 字符串
-
response.status:响应状态码
注意:
-
response.xpath方法的返回结果是一个类似list的类型,其中包含的是selector对象,操作和列表一样,但是有一些额外的方法
-
extract() 返回一个包含有字符串的列表
如果使用列表调用extract()则表示,extract会将列表中每一个列表元素进行extract操作,返回列表
-
extract_first() 返回列表中的第一个字符串,列表为空没有返回None
-
spider中的parse方法必须有
-
需要抓取的url地址必须属于allowed_domains,但是start_urls中的url地址没有这个限制
-
启动爬虫的时候注意启动的位置,是在项目路径下启动
6、配置settings文件
-
ROBOTSTXT_OBEY = False
robots是一种反爬协议。在协议中规定了哪些身份的爬虫无法爬取的资源有哪些。
在配置文件中setting,取消robots的监测:
-
在配置文件中配置全局的UA:USER_AGENT='xxxx'
-
在配置文件中加入日志等级:LOG_LEVEL = 'ERROR' 只输出错误信息
其它日志级别
-
CRITICAL 严重错误
-
ERROR 错误
-
WARNING 警告
-
INFO 消息
-
DEBUG 调试
-
代码实例
# Scrapy settings for mySpider project USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36' ROBOTSTXT_OBEY = False LOG_LEVEL = 'ERROR'
7、数据存储
7.1、使用终端命令行进行存储
-
代码配置
/myspider/myspider/spiders/ITSpider.py
class ITSpider(scrapy.Spider): name = 'ITSpider' # allowed_domains = ['www.xxx.com'] start_urls = ['https://duanzixing.com/page/2/'] # 通过终端写入文件的方式 def parse(self, response): article_list = response.xpath('/html/body/section/div/div/article') # 创建列表, 存储数据 all_data = [] for article in article_list: title = article.xpath('./header/h2/a/text()').extract_first() con = article.xpath('./p[2]/text()').extract_first() dic = { 'title': title, 'con': con } all_data.append(dic) return all_data
-
终端命令
scrapy crawl ITSpider -o ITSpider.csv
将文件存储到ITSpider.csv 文件中
7.2、利用管道pipeline来处理(保存)数据(写入文件中)
先跟着配置 后面会单讲
代码配置
-
打开items.py文件 添加如下代码
myspider/myspider/items.py
import scrapy class MyspiderItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() con = scrapy.Field()
-
/myspider/myspider/spiders/ITSpider.py
import scrapy from myspider.items import MyspiderItem class ITSpiderSpider(scrapy.Spider): name = 'ITSpider' # allowed_domains = ['www.xxx.com'] start_urls = ['https://duanzixing.com/page/2/'] # 写入管道 持久化存储 def parse(self, response): article_list = response.xpath('/html/body/section/div/div/article') for article in article_list: title = article.xpath('./header/h2/a/text()').extract_first() con = article.xpath('./p[2]/text()').extract_first() item = DuanziproItem() item['title'] = title item['con'] = con yield item
在爬虫文件ITSpider.py中parse()函数中最后添加
yield item
思考:为什么要使用yield?
-
让整个函数变成一个生成器,有什么好处呢?
-
遍历这个函数的返回值的时候,挨个把数据读到内存,不会造成内存的瞬间占用过高
-
python3中的range和python2中的xrange同理
注意:yield能够传递的对象只能是:BaseItem,Request,dict,None
-
-
打开管道文件 pipelines.py 添加如下代码
myspider/myspider/pipelines.py
class ITSpiderPipeline: f = None def open_spider(self, spider): print('爬虫开始时被调用一次') self.f = open('./duanzi.text', 'w') # 爬虫文件中提取数据的方法每yield一次item,就会运行一次 # 该方法为固定名称函数 def process_item(self, item, spider): print(item) self.f.write(item['title']+item['con']+'\n') return item def close_spider(self, spider): print('爬虫结束时被调用') self.f.close()
-
open_spider方法
重写父类中open_spider方法 只有爬虫开始十被调用一次
-
close_spider 方法
重写父类中lose_spider方法 爬虫结束时被调用一次
-
-
在settings.py设置开启pipeline
将默认被注释的管道打开
ITEM_PIPELINES = { 'myspider.pipelines.MyspiderPipeline': 300, }
其中数值代表优先级 数值越小优先级越高
8、运行scrapy
命令:在项目目录下执行scrapy crawl +<爬虫名字>
示例:scrapy crawl ITSpider