网络爬虫系列笔记(4)——Scrapy爬虫

xiaoxiao2021-02-28  112

Scrapy爬虫 Scrapy 不是一个简单的函数功能库;而是 一个专业的网络爬虫框架 Scrapy 足以支持一般商业服务所需的爬虫能力:持续爬取、商业服务、高可靠性 scrapy库的安装: pip install scrapy scrapy -h Available commands:   bench         Run quick benchmark test   commands   fetch         Fetch a URL using the Scrapy downloader   genspider     Generate new spider using pre-defined templates   runspider     Run a self-contained spider (without creating a project)   settings      Get settings values   shell         Interactive scraping console   startproject  Create new project   version       Print Scrapy version   view          Open URL in browser, as seen by Scrapy   [ more ]      More commands available when run from project directory Unit1、Scrapy爬虫框架 一、Scrapy爬虫框架结构 爬虫框架 爬虫框架是实现爬虫功能的一个软件结构和功能组件集合。是一个半成品,帮助实现专业网络爬虫。 “5+2”结构:                                  已有实现,不用编写    ENGINE            引擎 控制所有模块之间的数据流根据条件触发事件 SCHEDULER    调度器 对所有爬取请求进行调度管理,排访问顺序 ITEM PIPELINES (出口) 用户编写(也叫配置),对提取的信息进行后处理 以流水线来处理Spider产生的爬取项有一组操作顺序组成,类似流水线,每个操作是一个Item Pipeline类型可能操作包括:清理、检验、查重爬取项的HTML数据、将数据储存到数据库 SPIDERS            (入口)  用户编写(也叫配置),提供初始URL链接,并解析所得网页内容,再提供链接 解析Downloader返回的响应(Response)产生爬取项(scraped item)产生额外的爬取请求(Request) DOWNLOADER    下载页面Downloader Middlewares    (中间件) 目的:实施Engine、Scheduler、Downloader之间进行用户可配置的控制功能:修改、丢弃、新增请求或响应(拦截) Spider Middleware      (中间件) 目的:对请求和爬取项再处理功能:修改、丢弃、新增请求或爬取项(拦截) 二、Requests  vs. Scrapy 相同点: 都可进行页面请求和爬取,是Python爬虫的两个重要技术路线。两都好用,文档丰富,入门简单。都么有处理js、提交表单、应对验证码等功能(可扩展) 不同: requests Scrapy 页面级  网站级 功能库 框架 并发性不足,性能差 并发性好,性能较强(基于异步结构设计,有时太快会被反爬虫发现) 重点在于页面下载  重点在于爬虫框架 定制灵活 一般定制灵活,深度定制困难 上手十分简单 人门稍微难 三、Scrapy爬虫的常用命令 Scrapy命令行   (建立爬虫,运行爬虫) Scrapy 是为持续运行设计的专业爬虫框架,提供操作的Scrapy命令行。 >scrapy <command> [options] [args] 命令行输入: scrapy -h 常用命令: startproject 创建一个新工程 scrapy startproject <name> [dir] genspider 创建一个爬虫 scrapy genspider [options] <name> <domain> settings 获得爬虫配置信息 scrapy settings [options] crawl 运行一个爬虫 scrapy crawl <spider> list 列出工程中所有爬虫 scrapy list shell 启动URL调试命令行 scrapy shell [url] Scrapy为什么采用命令行? 命令行(而不是图形界面)更容易自动化,适合脚本控制。本质上,Scrapy是给程序员使用的,功能(而不是界面)更重要。
Unit2、Scrapy爬虫基本使用 产生步骤: 建立一个Scrapy爬虫工程 命令行:D:\pycode>scrapy startproject python123demo 生成工程目录: Python123demo/------>外层目录 scrapy.cfg  ------>部署Scrapy爬虫的配置文件,服务器Python123demo/-->Scrapy框架的用户自定义python代码 __init__.py-->初始化脚本items.py  -->Items代码模板(继承类)middlewares.py  -->Middlewares代码模板(继承类)pipelines.py  -->Pipelines代码模板(继承类)settings.py --->Scrapy爬虫的配置文件spiders/   ----->Spiders代码模板目录(继承类) __init__.py  ----->初始文件,无需修改__pycache__/--->缓存目录,无需修改 在工程中产生一个Scrapy爬虫,产生一个Spider模板 命令行:D:\pycode>cd python123demo    D:\pycode\python123demo>scrapy genspider demo python123.io #爬取域名   Created spider 'demo' using template 'basic' in module:  python123demo.spiders.demo作用:生成demo.py 编写产生的Spider模板 修改dome.py文件 运行爬虫,获取网页 start_urls = ['http://python123.io/ws/demo.html'] #等价方法,完整代码部分 : def start_requests(self):     urls = [             'http://python123.io/ws/demo.html'            ]     for url in urls:         yield scrapy.Request(url=url, callback=self.parse)#当Url数量很大时,可以很有效的节省资源 yield关键字                     yield <-->生成器 生成器:一个不断产生值的函数包含yield语句的函数是一个生成器生成器每次产生一个值(yield语句),函数被冻结,被唤醒后再产生一个值。 #生成器写法 def gen(n):      for i in range(n):           yield i**2 for i in gen(5):     print(i,' ', end="") #普通写法 def square(n):      ls = [i**2 for i in range(n)]      return ls for i in square(5):     print(i,' ', end="") ##当n=1M、10M、100M或更大?生成器的重要优势 为何要使用生成器? 生成器相比一次列出所有内容的优势 更节省储存空间响应更迅速使用更加灵活 Scrapy爬虫的使用步骤: 创建一个工程和Spider模板编写Spider编写Item Pipeline优化配置策略 Scrapy爬虫的数据类型: 1、Request类 (class scrapy.http.Request())      Request对象表示一个HTTP请求     由Spider生成,Downloader执行 属性、方法 .url .method .headers .body .meta .copy() 说明 对应URL 对应请求方法.'GET''POST' 字典类型请求 头 头部自定义 字符串类型请求内容 用户添加的扩展信息,Scrapy内部传递信息 复制该请求 2、Response类 (class scrapy.http.Request())  Request对象表示一个HTTP响应 由Downloader生成,Spider执行 属性和方法: .url .status .headers .body .flags .request .copy(0 对应URL HTTP状态码,默认200 头部 内容 一组标记 对应Request对象 复制该响应 3、Item类 (class scrapy.item.Item()) Item对象表示一个从HTML页面中提取的信息内容。由Spider生成,由Item Pipeline处理。Item类似字典类型,可以按照字典类型操作。 Scrapy爬虫提取信息的方法:      Beautiful Soup     lxml     re     XPath Selector     CSS Selector Xpath Selector: 举例 ##<div id="test1">大家好!</div> data = response.xpath('//div[@id="test1"]/text()').extract()[0] ##<div id="test3">我左青龙,<span id="tiger">右白虎,<ul>上朱雀,<li>下玄武。</li></ul>老牛在当中,</span>龙头在胸口。<div> data = response.xpath('//div[@id="test3"]') info = data.xpath('string(.)').extract()[0]       CSS Selector的基本使用:(由W3C组织维护并规范)           <HTML>.css('a::attr(href)').extract()                          a:标签名     href:标签属性 www.w3school.com.cn/cssref/css_selectors.asp     (参考链接) .class .intro 选择 class="intro" 的所有元素。 1 ::selection ::selection 选择被用户选取的元素部分。 element p 选择所有 <p> 元素。 1 element,element div,p 选择所有 <div> 元素和所有 <p> 元素。 1 element element div p 选择 <div> 元素内部的所有 <p> 元素。 1 spider中应用举例: start_urls = ["http://bj.lianjia.com/ershoufang/pg1tt2/"] def parse(self, response):         # 获取当前页面的房屋列表         #house_lis = response.css('.house-lst .info-panel')         # 把结果输出到文件(在命令行中房屋标题会因为编码原因显示为乱码)         with open("homelink.log", "wb") as f:             ## 使用css selector进行操作             #average_price = response.css(' .secondcon.fl li:nth-child(1)').css(' .botline a::text').extract_first()             #f.write("Average Price: " + str(average_price) + "\r\n")             #yesterday_count = response.css('.secondcon.fl li:last-child').css('.botline strong::text').extract_first()             #f.write("Yesterday Count: " + str(yesterday_count) + "\r\n")             #for house_li in house_lis:             #    link = house_li.css('a::attr("href")').extract_first()            # 获取房屋的链接地址             #    title = house_li.css('a::text').extract_first()                    # 获取房屋的标题             #    price = house_li.css('.price .num::text').extract_first()          # 获取房屋的价格 Unit2、实例4,股票数据Scrapy爬虫 要求同实例3 Scrapy爬虫步骤: 创建一个工程和Spider模板 scrapy startproject BaiduStockscd BaiduStocksscrapy genspider stocks baidu.com修改spiders/stocks.py文件 编写Spider 配置stocks.py文件修改对返回页面的处理修改对新增URL爬取请求的处理 编写Item Pipeline 配置pipelines.py文件定义对爬取项(Scrapy Item)的处理类配置Item_Pipelines选项(settings.py文件) 优化配置策略 配置并发连接选项(settings.py文件) CONCURRENT_REQUESTS     Downloader最大并发请求下载数量,默认32CONCURRENT_ITEMS    Item Pipeline最大并发ITEM处理数量,默认100CONCURRENT_REQUESTS_PER_DOMAIN     每个目标域名最大并发请求数量,默认8CONCURRENT_REQUESTS_PER_IP     每个目标IP最大并发请求数量,默认0,非0有效 执行程序 scrapy crawl stocks spider代码: (stocks.py文件源代码) # -*- coding: utf-8 -*- import scrapy import re class StocksSpider(scrapy.Spider):     name = "stocks"     start_urls = ['http://quote.eastmoney.com/stocklist.html']     def parse(self, response):         for href in response.css('a::attr(href)').ectract():             try:                 stock = re.findall(r'[s][hz]\d{6}', href)[0]                 url = 'https://gupiao.baidu.com/stock/' + stock + '.html'                 yield scrapy.Request(url, callback=self.parse_stock)                 #此处callback 给出处理该Url 所对应的函数             except:                 continue     def parse_stock(self, response):         infoDict = {}         stockInfo = response.css('.stock-bets')         name = stockInfo.css('.bets-name').extract()[0]         keyList = stockInfo.css('dt').extract()         valueList = stockInfo.css('dd').extract()         for i in range(len(keyList)):             key = re.findall(r'>.*</dt>', keyList[i])[0][1:-5]             try:                 val = re.findall(r'\d+\.?.*</dd>', valueList[i])[0][0:-5]             except:                 val = '--'         infoDict.update({'股票名称': re.findall('\s.*\(',name)[0].split()[0]+\         re.findall('\>.*\<', name)[0][1:-1]})         #使用yield,将结果封装成Item类,传给ItemPipeline         yield infoDict pipelines.py文件源代码: # -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html class BaidustocksPipeline(object):     def process_item(self, item, spider):         return item class BaidustocksInfoPipeline(object):     #爬虫启动时Pipeline对应的方法     def open_spider(self, spider):         self.f = open('BaiduStockInfo.txt', 'w')     #爬虫关闭时Pipeline对应的方法     def close_spider(self, spider):         self.f.close()     #对每一个Item进行处理时对应的方法:主体函数     def process_item(self, item, spider):         try:             line = str(dict(item)) + '\n'             self.f.write(line)         except:             pass         return item settings.py文件中被修改的区域: - # Configure item pipelines - # See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html - ITEM_PIPELINES = { -     'BaiduStocks.pipelines.BaidustocksInfoPipeline': 300, - } Unit3、扩展 表单提交、爬取周期、入库存储 requests-bs4-re           scrapy                         +               PhantomJS scrapyd-*          https://pypi.python.org Scrapy 爬虫的应用展望 普通价值: 基于Linux,7*24,稳定输出商业级部署和应用(scrapyd-*)千万规模内URL爬取、内容分析和存储 高阶价值: 基于docker,虚拟化部署中间件扩展,增加调度和监控各种反爬虫对抗技术
转载请注明原文地址: https://www.6miu.com/read-32920.html

最新回复(0)