Python-- Scrapy

scrapy爬虫框架

中文学习文档:https://scrapy-chs.readthedocs.io/zh_CN/0.24/index.html 

1、爬虫框架有哪些:

  • scrapy 
  • pyspider
  • crawley

2、scrapy框架介绍

3、安装

(这里安装会遇到很多错误,这里不再介绍,可以自己根据自己遇到的错误进行搜素解决方法)

4、scrapy包含的部件

  1. Engine:引擎负责控制系统所有组件之间的数据流,并在发生某些操作时触发事件。
  2. Scheduler:调度程序接收来自引擎的请求,并将它们排入队列,并在之后,当Engine需要的时候,将requests发送给engine。
  3. Downloader:下载器负责提取网页并将它们馈送到引擎,然后引擎将其发送给spider。
  4. Spiders:蜘蛛是Scrapy用户编写的自定义类,用于解析响应并从中提取item项目(也称为抓取的项目)或追加的其他请求。(负责把下载器得到的网页/结果进行分解,分解成数据+链接。)
  5. Item Pipeline:Item Pipeline负责处理被蜘蛛提取的item, 典型的任务包括清理,验证和持久性(如将项目存储在数据库中)。 这一部分在上一篇文章中也详细的介绍过了。
  6. Downloader middlewares:下载中间件,自定义下载的功能扩展组件。下载器中间件是位于引擎和下载器之间的特定的钩子,当它们从引擎传递到下载器时处理请求,以及从下载器传递到引擎的响应。使用下载中间件可以达成如下的目的:
    1. 在将请求发送到下载器之前处理请求(即在Scrapy将请求发送到网站之前)。在传递给蜘蛛之前改变接收到的响应;在传递给蜘蛛之前改变接收到的响应;
    2. 发送新的请求,而不是将接收到的响应传递给蜘蛛;
    3. 发送新的请求,而不是将接收到的响应传递给蜘蛛;向蜘蛛传递响应而不需要获取网页;
  7. SpiderMiddleware爬虫中间件(功能扩展组件):对spider进行功能扩展 

5、爬虫项目大概流程

  • 新建项目:scrapy startproject xxx
  • 明确需要目标/产出:  编写item.py
  • 制作爬虫:地址 spider/xxspider.py
  • 存储内容:pipelines.py,   

6、部件介绍

1、ItemPipeline

  • 对应的是pipelines文件
  • 爬虫提取出数据存入item后,item中保存的数据需要进一步处理,比如清洗,去重,存储等
  • process_item:
    • spider提取出来的item作为参数传入,同时传入的还有spider
    • 此方法必须实现
    • 必须返回一个Item对象,被丢弃的item不会被之后的pipeline处理
  • __init__:构造函数:进行一些必要的参数初始化     
  • open_spider(spider):spider对象被开启的时候调用
  • close_spider(spider):当spider对象被关闭的时候调用 

2、Spider

  • 对应的是文件夹spiders下的文件
  •  __init__: 初始化爬虫名称,start_urls列表
  • start_requests:生成Requests对象交给Scrapy下载并返回response
  • parse: 根据返回的response解析出相应的item,item自动进入pipeline; 如果需要,解析出url,url自动交给requests块,一直循环下去
  • start_request: 此方法仅能被调用一次,读取start_urls内容并启动循环过程
  • name:设置爬虫名称
  • start_urls:  设置开始第一批爬取的url
  • allow_domains:spider允许爬去的域名列表
  • start_request(self): 只被调用一次
  • parse
  • log:日志记录

3、中间件(DownloaderMiddlewares)

  • 中间件是处于引擎和下载器中间的一层组件
  • 可以有很多个,被按顺序加载执行
  • 作用是对发出的请求和返回的结果进行预处理
  • 在middlewares文件中
  • 需要在settings中设置以便生效
  • 一般一个中间件完成一项功能
  • 必须实现以下一个或者多个方法
    • process_request(self, request, spider)
      • 在request通过的时候被调用
      • 必须返回None或Response或Request或raise IgnoreRequest
      • None: scrapy将继续处理该request
      • Request: scrapy会停止调用process_request并冲洗调度返回的reqeust
      • Response: scrapy不会调用其他的process_request或者process_exception,直接讲该response作为结果返回
      • 同时会调用process_response函数
    • process_response(self, request, response,  spider)
      • 跟process_request大同小异
      • 每次返回结果的时候会自动调用
      • 可以有多个,按顺序调用

案例代码:

import random
import base64

# 从settings设置文件中导入值
from settings import USER_AGENTS
from settings import PROXIES

#  随机的 User-Agent
class RandomUserAgent(object):
	def process_request(self, request, spider):
		useragent = random.choice(USER_AGENTS)
		request.headers.setdefault("User-Agent", useragent)
		
class RandomProxy(object):
	def process_request(self, request, spider):
		proxy = random.choice(PROXIES)
		if proxy['user_passwd'] is None:
			#  没有代理账户验证的代理使用方式
			request.meta['proxy'] = "http://" + proxy['ip_port']
		else:
			#  对账户密码进行 base64 编码转换
			base64_userpasswd = base64.b64encode(proxy['user_passwd'])
			#  对应到代理服务器的信令格式里
			request.headers['Proxy-Authorization'] = 'Basic ' + base64_userpasswd
			request.meta['proxy'] = "http://" + proxy['ip_port']

7、设置settings的相关代码 

USER_AGENTS = [
			"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR
			3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
			"Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0;
			SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET
			CLR 1.1.4322)",
			"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR
			2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
			"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko,
			Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
			"Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3)
			Arora/0.6",
			"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-
			Ninja/2.1.1",
			"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0
			Kapiko/3.0",
			"Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5"
			]           

PROXIES = [
		{'ip_port': '111.8.60.9:8123', 'user_passwd': 'user1:pass1'},
		{'ip_port': '101.71.27.120:80', 'user_passwd': 'user2:pass2'},
		{'ip_port': '122.96.59.104:80', 'user_passwd': 'user3:pass3'},
		{'ip_port': '122.224.249.122:8088', 'user_passwd': 'user4:pass4'},
		]

8、去重

  • 为了放置爬虫陷入死循环,需要去重
  • 即在spider中的parse函数中,返回Request的时候加上dont_filter=False参数
myspeder(scrapy.Spider):
	def parse(.....):
	
		......
		
		yield  scrapy.Request(url=url, callback=self.parse, dont_filter=False)                

9、如何在scrapy使用selenium

  • 可以放入中间件中的process_request函数中
  • 在函数中调用selenium,完成爬取后返回Response 
calss MyMiddleWare(object):
	def process_request(.....):
		
		driver = webdriver.Chrome()
		html = driver.page_source
		driver.quit()
		
		return HtmlResponse(url=request.url, encoding='utf-8', body=html, request=request)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章