两周从爬虫小白变大神,看完你就知道我不是标题党了

selenium框架

以driver程序驱动浏览器,对目标(网站或网页)进行操作(请求网页、提取数据、截图、切换或关闭页签-window)。

- chrome.get() 打开目标(发起请求)

  • chrome.quit() 退出浏览器

  • chrome.close() 关闭当前的窗口

  • chrome.find_element(By, value)

  • selenium.webdriver.common.by.By

  • ID

  • CLASS_NAME

  • NAME

  • XPATH

  • CSS_SELECTOR

_ LINK_TEXT

  • WebElement 查到的标签对象

  • get_attribute(‘属性名’, default)

  • text 标签文本

  • click()

  • send_keys()

  • rect 当前元素的位置(left, top, width, height)

  • chrome.find_elements(By, value)

  • execute_script()

  • save_screenshot(filename) 截图

  • 等待某一个标签元素出现

  • selenium.webdriver.support

  • ui

  • WebDriverWait

  • expected_conditions

  • visibility_of_all_elements_located((By, value))

ui.WebDriverWait(dirver, timeout).until(

expected_conditions,

error_msg

)

docker

容器技术,将远程的docker仓库中的镜像下拉到本地, 再将镜像运行成为一个容器(进程)。

- 镜像操作

  • 基本信息

  • 名称

  • 版本

  • ID

  • 描述

  • docker images 查看所有镜像

  • docker rmi 名称:版本号 / ID 删除镜像

  • docker run 名称:版本号 / ID 启动镜像

  • -dit 后台启动镜像,启动后可进入容器并打开新的terminal(终端)

  • -p 宿主机端口: 容器端口

  • 容器操作

  • docker ps 查看正运行的容器

  • -a 查看所有的容器

  • -l 查看最后一个启动的容器

  • docker logs 容器名或ID 查看容器运行的日志

  • docker exec 容器名或ID Linux命令 在容器中执行Linux命令

  • docker exec -it 容器名或ID bash 进入容器

  • docker stop 容器名或ID

  • docker start 容器名或ID

  • docker restart 容器名或ID

  • docker rm -f 容器名或ID 删除容器, -f强制删除正运行的容器

日志模块进阶

日志格式

| 格式 | 说明 |

| — | — |

| %(name)s | 记录器的名称, 默认为root |

| %(levelno)s | 数字形式的日志记录级别 |

| %(levelname)s | 日志记录级别的文本名称 |

| %(filename)s | 执行日志记录调用的源文件的文件名称 |

| %(pathname)s | 执行日志记录调用的源文件的路径名称 |

| %(funcName)s | 执行日志记录调用的函数名称 |

| %(module)s | 执行日志记录调用的模块名称 |

| %(lineno)s | 执行日志记录调用的行号 |

| %(created)s | 执行日志记录的时间 |

| %(asctime)s | 日期和时间 |

| %(msecs)s | 毫秒部分 |

| %(thread)d | 线程ID |

| %(threadName)s | 线程名称 |

| %(process)d | 进程ID |

| %(message)s | 记录的消息 |

- Python脚本中执行当前操作系统的命令的方法

  • os.chdir() 切换当前目录

  • os.system() 无返回结果 (打开一个子进程执行 命令)

  • os.popen() 可读取返回结果

日志模块的核心

  • 四大核心

  • 日志记录器 Logger

  • 日志处理器Handler

  • 日志的过滤器Filter

  • 日志的格式化Formatter

scrapy框架

scrapy架构组成

  • 五个核心

  • engine 引擎, 协调其它四个组件之间的联系,即与其它四个组件进行通信,也是scrapy框架的核心。

  • spider 爬虫类, 爬虫程序的编写代码所在, 也是发起请求的开始的位置。spider发起的请求,经过engine转入到scheduler中。

  • scheduler 调度器, 调度所有的请求(优先级高,则会先执行)。当执行某一个请求时,由engine转入到downloader中。

  • donwloader 下载器, 实现请求任务的执行,从网络上请求数据,将请求到的数据封装成响应对象,并将响应的对象返回给engine。engine将数据响应的数据对象(以回调接口方式)回传给它的爬虫类对象进行解析。

  • itempipeline 数据管道, 当spider解析完成后,将数据经engine转入到此(数据管道)。再根据数据类型,进行数据处理(图片、文本)

  • 二个中间件

  • 爬虫中间件, 介于Spider和Engine之间的,可以拦截Spider的发起的请求及数据。

  • 下载中间件,介于Engine和Downloader之间的,可以拦截下载和响应。当然在下载处理之前,可以设置代理 、请求头、Cookie等操作(反反爬设置),还可以基于Splash或Selenium实现特定的操作。

scrapy指令

  • 创建项目命令

  • scrapy startproject 项目名称

  • 创建爬虫命令

  • scrapy genspider 爬虫名 域名

  • 启动爬虫命令

  • scrapy crawl 爬虫名

  • 调试爬虫命令

  • scrapy shell url

  • scrapy shell

  • fetch(url)

Response类

  • 属性相关【重点】

  • body 响应的字节数据

  • text 响应的编码之后文本数据

  • headers 响应头信息, 是字节数据

  • encoding 响应数据的编码字符集

  • status 响应的状态码

  • url 请求的url

  • request 请求对象

  • meta 元数据,用于request和callback回调函数之间传值

  • 解析相关【重点】

  • selector()

  • css() 样式选择器 , 返回Selector选择器的可迭代(列表)对象

  • scrapy.selector.SelectorList 选择器列表

  • x()/xpath()

  • scrapy.selector.Selector 选择器

  • 样式选择器提取属性或文本

  • ::text 提取文本

  • ::attr("属性名") 提取属性

  • xpath() xpath路径

xpath路径,同lxml的xpath()写法

  • 选择器常用方法

  • css()/xpath()

  • extract() 提取选择中所有内容,返回是list

  • extract_first()/get() 提取每个选择器中的内容, 返回是文本

Request类

  • scrapy.http.Request

请求对象的属性

  • url

  • callback 解释数据的回调函数对象

  • headers 请求头

  • priority 请求的优先级, 值越高,优先级越高(优先下载)

作业

  • 写出selenium向下和向右滚动的脚本

document.documentElement.scrollTop 向下

document.documentElement.scrollLeft 向右

  • 写出restful接口设计规范(四个)

  • 每个资源都有唯一标识 URI

  • 每个资源具有四个动作, GET|POST|PUT|DELETE

  • 每次请求都是无状态

  • 接口交互的数据是json或xml

  • 写出常见的反爬虫和反反爬虫

  • 访问次数 - IP代理

  • Cookie验证- Cookie池

  • UA验证 - UA池

  • 验证码 - 打码平台

  • 动态js渲染 - Selenium/Splash

  • 爬取 陕西省政府采购网 陕西省采购网

  • 基于Flask实现日志上报服务器(日志微服务)

  • logging.handlers.HTTPHandler

爬虫第七天


回顾知识点

日志模块

import logging

from logging import StreamHandler, FileHandler

  • 四个核心部分

  • 日志记录器logger: 记录日志信息

  • 日志处理器 handler: 记录信息之后,由handler去处理

  • 日志过滤器 filter: 对记录信息进行过滤。

  • 日志格式化 formatter: 由处理器对记录的信息按formatter格式进行处理(除HTTPHandler和SMTPHandler之外)。

  • 核心方法或函数

  • logging.getLogger(name) # 默认没有name时,返回root

  • logging.baseConfig() 配置root记录器的格式、处理器等。

  • logging.info()/debug()/warning()/error()/critical() 由root记录器记录日志信息。

  • logger记录器的核心方法

  • setLevel(logging.DEBUG|INFO|WARNING|ERROR|FATAL)

  • addHandler(handler)

  • addFilter(Filter)

  • debug()|info()….

  • handler处理器的核心方法

  • setLevel(logging.DEBUG|INFO|WARNING|ERROR|FATAL)

  • setFormatter(fmt)

  • Formatter初始化参数

  • format 格式化的字符串, 使用%(日志变量)s 相关日志变量占位符组成的字符串

‘hi, %(name)s, age is %(age)s’ % {‘age’: 20, ‘name’: ‘jack’}

‘hi, %s, age is %s’ % (‘disen’, 30)

  • datefmt 指定 %(asctime)s 日志时间的格式, 通常使用 %Y-%m-%d %H:%M:%S年月日 时分秒格式。

scrapy框架

五大组件两个中间件

  • engine 核心引擎

  • spider 爬虫类

  • scheduler 调度器

  • downloader 下载器

  • itempipeline 数据管道

  • 爬虫中间件、下载中间件

scrapy指令

  • scrapy startproject 项目名

  • scrapy genspider 爬虫名 域名

  • scrapy crawl 爬虫名

  • -o 保存数据到指定的文件中

  • -s 信号(CLOSESPIDER_ITEMCOUNT=30)

  • scrapy shell [url]

  • fetch(url)

  • view(response)

  • request: scrapy.http.Request

  • response: scrapy.http.Response|HtmlResponse

  • scrapy

Response对象的属性或方法

  • body|text|encoding|status|url|request|headers|meta

  • xpath()|css() -> scrapy.selector.SelectorList[Selector]

  • extract()

  • get()

  • extract_first()

  • css() 中表达式

  • 样式选择器[::text|attr("属性名")]

  • xpath()中表达式

同lxml的xpath表达式相同。

Request初始化参

  • url

  • callback 如果未指定,则默认为 parse

  • priority 优先级的权限值, 值高优先级高

  • meta

  • headers

  • dont_filter 是否过滤重复的url, True不过滤,Flase过滤.

scrapy数据管道

指令方式存储

scrapy crawl 爬虫名 -o xxx.json|csv

只适合单页数据爬取,如果多页多层次数据爬取时,不适合此方式。

Item类

作用: 用于区别中哪一页(类型)的数据

用法: 类似于dict用法, 在数据管道类的process_item()方法中,通过isinstance()方法来判断item是哪一类型的。

import scrapy

class BookItem(scrapy.Item):

book_id = scrapy.Field()

book_name = scrapy.Field()

book_cover = scrapy.Field()

book_url = scrapy.Field()

author = scrapy.Field()

tags = scrapy.Field()

summary = scrapy.Field()

class SegItem(scrapy.Item):

book_id = scrapy.Field()

seg_id = scrapy.Field()  # 章节ID

title = scrapy.Field()

url = scrapy.Field()

class SegDetailItem(scrapy.Item):

seg_id = scrapy.Field()  # 章节ID

content = scrapy.Field()  # 内容

Pipeline

  • 处理数据的方法

def process_item(self, item, spider):

return item

  • item参数表示 爬虫类中解释到的数据(yield item)

  • spider参数 表示爬虫类对象

  • 如果item被返回,则表示可以被优先级低的pipeline处理

  • 初始化方法

属于定制方法,可以初始化一些参数或对象,如文件名, 数据库的连接等。

  • process_iteminit的调用次数说明

  • process_item方法 会被(engine)多次调用

  • init随着爬虫程序的启动时创建pipeline类时调用,只会被调用一次

定量爬虫

基于信号方式

scrapy crawl -s 信号

常用的scrapy信号

  • **CLOSESPIDER_ITEMCOUNT=**条目的数量

  • CLOSESPIDER_PAGECOUNT=请求页的数量

  • CLOSESPIDER_ERRORCOUNT=请求错误的数量

  • CLOSESPIDER_TIMEOUT=超时的时长

scrapy crawl wanben -s CLOSESPIDER_ITEMCOUNT=10

下载中间件

爬虫中间件

监测爬虫类与引擎之间的交互数据(请求 request、响应 response、数据item)及异常情况

@classmethod

def from_crawler(cls, crawler): pass  # 启动爬虫时用于创建爬虫中间件类的实例对象

def process_spider_input(self, response, spider) # 流程中第6步,engine将请求响应的数据输入给spider时,调用此方法。

def process_spider_output(self, response, result, spider) # 流程中第7步,由spider类解析response数据之后产生结果输出给engine时,调用此方法

def process_spider_exception(self, response, exception, spider): # 解析数据时发异常时

def process_start_requests(self, start_requests, spider): # 第一次爬虫发起请求时,调用此方法,即流程中第1步,从Spider->Engine时。

下载中间件 [重点]

下载中间件是引擎engine和下载器downloader之间的中间件,可以拦截请求和响应以及请求异常的处理。

@classmethod

def from_crawler(cls, crawler)

def process_request(self, request, spider)

def process_response(self, request, response, spider)

def process_exception(self, request, exception, spider)

  • **process_request()**方法可返回的对象(四种可能)

  • scrapy.http.Request

  • scrapy.http.HtmlResponse/Response

  • None 表示不拦截

  • raise IgnoreRequest 不下载这个请求

  • **process_response()**方法可以返回的对象

  • scrapy.http.Request 未下载成功请求

  • scrapy.http.Response 进一步封装之后的response

4.3 作用

在下载中间件中,可以设置代理、设置cookie、设置请求头以及基于Selenium实现动态js渲染和用户登录。

作业

  • 写出scrapy的工作流程中第3、6两个步骤的描述

第3步: 引擎从调度器中获取下载任务, scheduler -> engine

第6步: 引擎从下载器获取的响应传递给spider, 用于解析。engine-> spider。 ( response.request.callback(response) )

  • 写出logging.baseConfig()方法的参数(4+)

logging.baseConfig(filename,  # 文件处理器参数

mode=“a”,  # 文件处理器参数

format,    # formatter

datefmt,   # formatter

handlers,  # addHandler(),

filters,   # addFilter()

stream)    # filename设置后, stream无效

  • 根据左边AA表结构和右边的查询结果,写出查询的SQL

---------------------------       ----------------------

| year | month | amount |       | year | m1 |   m2 |

---------------------------       ----------------------

| 1991 |   1   | 1.1   |       | 1991 | 1.1 | 1.2 |

---------------------------       ----------------------

| 1991 |   2   | 1.2   |       | 1992 | 2.1 | 2.2 |

---------------------------       ----------------------

| 1992 |   1   | 2.1   |


| 1992 |   2   | 2.2   |


  • join连接表方式

select a1.year, a1.amount as m1, a2.amount as m2

from AA a1

join AA a2 on (a1.year = a2.year)

where a1.month=1

and a2.month=2;

  • if/case判断函数方式

select if(条件, 成立的结果, 不成立的结果);

select year,

max(round(if(month=1, amount, 0),1)) m1,

max(round(if(month=2, amount, 0),1)) m2

from AA

group by year;

select year,

max(round(m1, 1)) as m1,

max(round(m2, 1)) as m2

from (

select year,

case when month=1 then amount else 0 end as m1,

case when month=2 then amount else 0 end as m2

from AA

) a

group by year;

select year,

max(round(m1, 1)) as m1,

max(round(m2, 1)) as m2

from (

select year,

case month when 1 then amount else 0 end as m1,

case month when 2 then amount else 0 end as m2

from AA

) a

group by year;

爬虫第八天


回顾知识点

数据处理

  • 启动爬虫的指令中带有 -o参数, 指定数据存储的文件(csv/json/xml)位置

  • 数据管道 pipeline

  • settings.py中配置管道类

  • process_item(self, item, spider) 管道类的处理数据的方法

  • 通过isinstance() 判断item属于哪一种类型, 然后按某一类型进行处理

  • 扩展 Python的自省相关函数

type(obj)  获取对象的类型

dir(obj)   获取对象中所有的属性(函数、类、变量)

help(obj)  获取对象的文档帮助信息

isinstance(obj, 类) 判断obj是否为类的实例对象

issubclass(类, 父类) 判断类是否为父类的子类

hasattr(对象, 属性或方法)  判断对象中是否存在属性或方法

getattr(对象, 属性或方法)  获取对象中的属性或方法

setattr(对象, 属性, 属性值) 设置对象的属性或方法

id(对象) 获取对象在内存中的唯一标识

  • 返回item: 目的是让优先级低的数据管道类可以接收到item数据。

中间件

  • 爬虫中间件(scrapy工作流中第1, 第6, 第7等3个步)

@classmethod

def from_crawler(self, crawler)

def process_spider_input(self, response, spider)

def process_spider_output(self, response, result, spider)

def process_spider_exception(self, response, exception, spider)

def process_start_requetst(self, start_requests, spider)

def spider_opened(self, spider)

  • 下载中间件 (第4, 5两个步骤)

@classmethod

def from_crawler(self, crawler)

def process_request(self, request, spider):

return None|Request|Response| raise IgnoreRequest

def process_response(self, request, response, spider)

return response|request

def process_exception(self, request, excecption, spider)

def spider_opened(self, spider)

规则爬虫

  • 创建规则爬虫的指令

scrapy genspider -t crawl 爬虫名 域名

  • 链接提取器 LinkExctractor

  • 正则方式 (allow | deny)

  • restrict_xpaths() xpath方式指定a标签所在的(间接)父级标签

  • restrict_css() 样式方式指定a标签所在的(间接)父级标签

  • Rule() 规则

  • extractor: LinkExtractor

  • callback: str

  • follow=True 表示提取的连接在请求成功后,解析时是否继续按此规则提取连接

  • 不能重写parse()函数 【注】

规则爬虫【重】

LinkExtractor 类

作用: 提取感兴趣的a标签中的连接href属性, 因此在指定正则表过式,参考某些a标签中href属性的写法。如果正则提取困难,则支持css或xpath两个方式来指定a标签所在的父级标签。

核心的类

  • scrapy.spiders.CrawlSpider 规则爬虫类

重写了parse()解析函数,在此函数中通过指定规则中的LinkExtractor对象来提取当前响应数据中的连接,并向engine发起新的请求。新的请求中包含提取的连接url和rule中的回调函数。

def parse(self, response):

return self._parse_response(response,

self.parse_start_url, cb_kwargs={}, follow=True)

def _parse_response(self, response, callback, cb_kwargs, follow=True):

if callback:

cb_res = callback(response, **cb_kwargs) or ()

cb_res = self.process_results(response, cb_res)

for requests_or_item in iterate_spider_output(cb_res):

yield requests_or_item

if follow and self._follow_links:

for request_or_item in self._requests_to_follow(response):

yield request_or_item

def _requests_to_follow(self, response):

if not isinstance(response, HtmlResponse):

return

seen = set()

for n, rule in enumerate(self._rules):

links = [lnk for lnk in rule.link_extractor.extract_links(response)

if lnk not in seen]

if links and rule.process_links:

links = rule.process_links(links)

for link in links:

seen.add(link)

r = self._build_request(n, link)

yield rule.process_request®

  • scrapy.spiders.Rule 规则类

  • extractor: LinkExtractor

  • callback:str

  • follow:bool

  • scrapy.linkextractors.LinkExtractor 链接提取器类

  • allow

  • deny

  • restrict_xpaths

  • restrict_css

  • 创建规则爬虫是使用 -t crawl 模板

scrapy genspider -t crawl 爬虫名 域名

图片管道

使用ImagesPipeline

  • settings.py配置

  • IMAGES_STORE 指定数据存放的位置

  • ITEM_PIPELINES字典中,引入scrapy.pipelines.images.ImagesPipeline

  • 配置缩略图

IMAGES_THUMBS = {

‘small’: (with, height),

‘big’: (widht, height)

}

  • item数据属性

  • image_urls: list 表示下载图片地址的列表

  • images: list 表示下载完成后的图片存放在IMAGES_STORE中的路径及相关的属性

自定义ImagesPipeline

实现ImagesPipeline的子类,重写三个核心的方法。

三个核心的方法:

  • get_media_requests(self, item, info) 根据item中图片连接的属性,返回图片下载的request。

可以返回一个Request也可以多个Request的列表

  • file_path(self, request, response, info) 根据请求和响应返回图片保存的位置(相对于IMAGES_STORE)。

如果返回的路径中包含子路径时,系统会自动创建子目录( os.makedirs() )。

  • item_completed(self, results, item, info) 图片下载完成后,从results的结果获取图片的保存路径,并设置到item中,最后返回这个item。

results格式

[

(True, {‘path’: ‘’, ‘url’: ‘’, chucksum: ’ '} ),

(True, {‘path’: ‘’, ‘url’: ‘’, })

]

其它技术点

日志

scrapy的日志记录器在爬虫类对象中, 是logger, 通过爬虫对象的logger来记录运行的信息。scrapy的logger日志记录器使用了Adpater设计模式的logging.LoggerAdapter类。

【扩展】构建器设计模式 Builder ( 函数式-流式编程 )

car: Car = CarBuilder().step1().step2().step3().step4().build()

text = response.xpath().css().xpath().css().xpath().get()

Python开发人员需要掌握的设计模式: 单例、工厂、装饰器、适配器、构建器、生产者消费者(消息队列-订阅/发布)。

配置

在settings.py文件中,指定收集日志的等级及日志存储的文件名

LOG_LEVEL = ‘’ # DEBUG|INFO|ERROR|WARNING|CRITICAL

LOG_FILE = ‘文件名’ # os.path.join(BASE_DIR, ‘access.log’)

在程序中使用

  • 爬虫日志记录器

spider.logger.info()/error()

  • 获取scrapy中其它的记录器

  • 内置的记录器

- scrapy.utils.log

  • scrapy.crawler

  • scrapy.middleware

  • scrapy.downloadermiddlewares.httpauth|downloadtimeout…

  • scrapy.core.engine

  • scrapy.utils.signal

logging.getLogger(‘scrapy.utils.log’).info()/warning()

  • 自定义记录器

error_logger = logging.getLogger(‘dushu-project’)

error_logger.setLevel(logging.ERROR)

handler = logging.FileHandler(

os.path.join(BASE_DIR, ‘error.log’),

encoding=‘utf-8’

)

handler.setLevel(logging.ERROR)

handler.setFormatter(logging.Formatter(

‘%(asctime)s %(name)s at %(lineno)s of %(pathname)s : %(message)s’

))

error_logger.addHandler(handler)

使用时

from dushu.settings import error_logger

error_logger.error(‘消息’)

post请求

  • scrapy.http.FormRequest

  • url

  • formdata: dict( value必须都是字符串类型)

  • cookies: dict

  • headers: dict

  • callback 默认parse

  • 如果爬虫中第一次的请求是post请求,则重写Spider类的start_requests()方法

def start_requests(self):

self.url = ‘http://ccgp-shaanxi.gov.cn/notice/noticeaframe.do?noticetype=3&province=province&isgovertment=’

self.data = {

‘page.pageNum’: ‘1’

}

self.MAX_PAGE = 1399

yield FormRequest(self.url, formdata=self.data)

不需要指定start_urls 列表。

Selenium中间件

作用: 动态渲染js(ajax加载数据)

4.3.1 定义下载中间件类

class LoadDataMiddleware():

@classmethod

def from_crawler(cls, crawler):

This method is used by Scrapy to create your spiders.

s = cls()

crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)

crawler.signals.connect(s.spider_closed, signal=signals.spider_closed)

return s

  • 连接打开爬虫类的信号,在处理函数中打开chrome

def spider_opened(self, spider):

创建Selenium的Chrome浏览器对象

chromedriver.exec 所在的目录已配置到环境变量Path中

options = Options()

options.add_argument(‘–headless’)

options.add_argument(‘–disable-gpu’)

self.chrome = Chrome(options=options)

  • 连接关闭爬虫类的信号,在处理函数中退出chrome

def spider_closed(self, spider):

self.chrome.quit()

  • 处理process_request()方法编写核心业务

def process_request(self, request, spider):

判断是否为第一次请求

if not request.meta.get(‘next_page’, False):

self.chrome.get(request.url)

else:

点击下一页

self.chrome.execute_script(‘var q=document.documentElement.scrollTop=1200’)

time.sleep(0.5)

self.chrome.execute_script(‘var q=document.documentElement.scrollLeft=1000’)

time.sleep(0.5)

self.chrome.find_elements_by_xpath(‘//ul[@class=“pagination”]/li/a’)[-2].click()

time.sleep(2)

html = self.chrome.page_source

return HtmlResponse(request.url, body=html.encode(‘utf-8’))

配置

DOWNLOADER_MIDDLEWARES = {

‘caigou.middlewares.LoadDataMiddleware’: 543,

}

爬虫类

class ShaanxiSpider(scrapy.Spider):

name = ‘shaanxi2’

allowed_domains = [‘ccgp-shaanxi.gov.cn’]

start_urls = [‘http://ccgp-shaanxi.gov.cn/notice/noticeaframe.do?noticetype=3&province=province&isgovertment=’]

start_urls = [‘http://ccgp-shaanxi.gov.cn/notice/list.do?noticetype=3&province=province’]

def parse(self, response):

trs = response.css(‘.list-box tbody tr’)

for tr in trs:

item = {}

item[‘id’] = tr.xpath(‘./td[1]/text()’).get()

item[‘area’] = tr.xpath(‘./td[2]/text()’).get()

item[‘title’] = tr.xpath(‘./td[3]/a/text()’).get()

item[‘url’] = tr.xpath(‘./td[3]/a/@href’).get()

item[‘date’] = tr.xpath(‘./td[4]/text()’).get()

yield item

获取下一页数据

if len(trs) == 15:

yield Request(response.request.url,

meta={‘next_page’: True}, dont_filter=True)

dont_filter=True 原因是可能会被认为是重复, 让engine不去过滤重复的url。

作业

  • 定量爬虫的指令有哪些

CLOSESPIDER_ITEMCOUNT item数据条目量

CLOSESPIDER_PAGECOUNT 请求成功响应的次数

  • 下载中间件类的处理请求的方法是什么,可以返回哪些对象

def process_request(self, request, spider):

return None|Request|Response | rasie IgnoreRequest

  • None 表示不拦截当前的请求

  • Request 重新返回新的请求, engine将这个新请求压入到Scheduler中

  • Response 表示不需要下载器下载,由自己程序下载并且封装成Response对象。

  • raise IgnoreRequest 取消当前的request请求(重复, 过滤的)

  • 简述中间件from_crawler(self, crawler)函数的作用

当爬虫程序启动后,用于创建当前中间件类实例的方法。

可以监听爬虫程序是否正常启动。

【扩展】类方法、静态方法和实例方法的区别??

类方法:类对象(由元类创建类的对象)的方法,第一个参数是cls(表示当前类本身)。

@classmethod 修饰的方法

类实例方法: 由类的__new__()函数处理的类实例对象的方法,第一个参数是self(表示当前类的实例)

静态方法: 和类没有任何关系,只是在当前类中声明,方法的参数不会出现cls和self。

@staticmethod 修改的方法

【扩展】什么是抽象方法?

抽象方法是在父类中声明(没有实现功能),由子类实现的方法。如果子类中未实现,则会在调用时报错。

class Animal():

def eat(self): # 抽象方法

raise Exception(‘子类中必须实现此方法!’)

class Pig(Animal):

def eat(self):

print('Pig eat ', ‘ddd’)

class Dog(Animal):

def eat(self):

print('Dog eat ', ‘abc’)

爬虫第九天


回顾知识点

规则爬虫

  • scrapy.spiders.CrawlSpider 所有规则爬虫类的父类

  • scrapy.spiders.Rule 规则类

  • LinkExtractor 连接提取类的实例对象

  • callback: str 指定提取器提取的连接请求成功之后的数据解析的函数

  • follow: bool 表示对提取连接请求成功后的数据是否继续提取连接

  • scrapy.linkextractors.LinkExtractor

  • allow: str 提取连接中的href的正则表示

  • deny: str 拒绝提取连接中的href的正则表示

  • restrict_xpaths 以xpath的路径方式指定a所在的父级标签

  • restrict_css 以css的样式选择器方式指定a所在的父级标签

  • 创建规则爬虫的指令

scrapy genspider -t crawl 爬虫名 域名

日志

  • logging.LoggerAdapter 日志适配器类, 封装日志记录器和spider等相关消息

  • 每个爬虫类都存在它的日志记录器,记录器名称即是爬虫名(self.name)

  • 在中间件或管道等相关处理数据(item/request/response)的方法中都存在spider对象

spider.logger.info()/error()…记录日志

  • 在settings.py中配置日志记录的等级及日志文件存储的位置

LOG_LEVEL=‘INFO’

LOG_FILE = ‘/var/log/xxx.log’

  • 可以自定义日志记录器(可以声明一个日志处理模块-log_

dushu

|—dushu

|—spiders

|—item.py

|—middleware.py

|—pipeline.py

|—settings.py

|—log_

|–__init__.py

|—scrapy.cfg

log_.__init__.py文件中的内容:

import logging

from logging import Formatter, FileHandler

logger = logging.getLogger(‘dushu’)

logger.setLevel(logging.INFO)

handler = FileHandler(‘/var/log/dushu.log’)

handler.setLevel(logging.INFO)

handler.setFormatter(Formatter(format=‘%(asctime)s: %(message)s’,

datefmt=‘%Y-%m-%d %H:%M:%S’))

logger.addHandler(handler)

from dushu.log_ import logger

logger.info(‘记录的信息’)

ImagesPipeline

  • scrapy.pipelines.images.ImagesPipeline 配置在settings.py的ITEM_PIPELINES={}

  • 在settings.py文件配置图片存储的位置

IMAGES_STORE = ‘/var/src/images’

  • 在爬虫类的parse()中,指定item的image_urlsimages

  • 自定义ImagesPipeline

  • 声明ImagesPipeline的子类

  • 重写get_media_requests(self, item, info)方法, 在此方法中获取item的图片下载地址,返回相关的Request(url, meta={‘name’: item[‘name’]})

  • 重写file_path(self, request, response, info)方法, 在此方法中返回相对于IMAGEs_STORE图片存储的相对路径

return ‘%s/%s.jpg’ %(dir_name, file_name)

  • 重写item_completed(self, results, item, info),在此方法中,从results中获取下载文件存储的路径, 并添加到item中

path = [ data[‘path’] for ok, data in results if ok]

item[‘path’] = ‘,’.join(path)

return item

Selenium下载中间件

  • 声明一个类, 并将此类配置在DOWNLOADER_MIDDLEWARES={}

  • 声明from_crawler(self, crawler) 创建当前中间件类的实例的, 在此方法中指定spider_openedspider_closed两个信号的处理方法

  • 在spider_opened()方法中,创建Chrome浏览器的驱动对象

  • 在spider_closed()方法, 将chrome浏览器对象进行退出

  • 声明process_request(self, request, spider) 处理每个请求

self.chrome.get(request.url)

…等待某个UI元素出现

html = self.chrome.page_sources

return scrapy.http.HtmlResponse(request.url, body=html.encode(‘utf-8’))

分布式爬虫

什么是分布式

  • Hadoop 分布式计算框架(大数据处理)HDFS(分布式文件系统)

  • MapReduce

  • Hbase 数据库

  • Hive 实时数据库

  • Spark 大数据平台(MySQL、Hbase)

  • 由多个服务器(操作系统-PC)组成,在调度器调度的情况下完成不同的任务,这种架构称之为分布式。常见的调度器是消息中间件、服务注册中心、负载均衡等组成。

常见消息队列

  • Redis订阅与发布-实现消息队列

  • RabbitMQ 基于Channel实现消息队列

  • Kafka 消息队列

scrapy-redis

  • 安装包: pip install scrapy-redis

  • 配置调度器类、去重类及消息中间件(队列的位置)

SCHEDULER=“scrapy_redis.scheduler.Scheduler”

SCHEDULER_PERSIST=True

DUPEFILTER_CLASS = “scrapy_redis.dupefilter.RFPDupeFilter”

REDIS_URL=‘reids://[:password@]host-ip:6379/1’ # 0-15数据库索引

  • 修改爬虫类

  • 父类 scrapy_redis.spiders.RedisSpider|RedisCrawlSpider

  • 去掉start_urls 列表

  • 增加redis_key 字符串变量, 指定redis服务中存储的key

  • 按正常启动爬虫程序命令启动爬虫

scrapy crawl 爬虫名

  • 连接redis服务,向redis_key的列表list中推送请求任务

lpush xxxx http://www.xxxx.com/xxx/

爬虫程序部署

scrapyd

  • 安装scrapyd服务和客户端

pip install scrapyd scrapyd-client

  • 如果在云服务器安装scrapyd

  • 修改scrapyd源码中app.py文件

bind_addres = ‘0.0.0.0’

  • 在云服务的安全组中,放开6800端口

  • 在scrapyd服务启动Python环境中安装爬虫需要的依赖库

  • 修改爬虫项目scrapy.cfg文件

[deploy:100]

url = http://119.3.170.97:6800/

project = dushu_redis

  • 使用scrapyd-deploy命令发布项目

scrapyd-deploy 100 -p dushu_redis

请求成功后,返回json数据,包含job_id数据,用于停止爬虫。

docker部署

编写Dockerfile文件

FROM 119.3.170.97:5000/ubuntu:latest

MAINTAINER disen 610039018@qq.com

ADD . /usr/src

WORKDIR /usr/src

VOLUME /usr/src

RUN pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple

RUN chmod +x run.sh

CMD /usr/src/run.sh

  • ADD 命令将当前目录下所有文件复制到容器的/usr/src目录下

  • WORKDIR 容器中切换当前的工作目录,类似于cd

  • VOLUME 将容器中的文件位置暴露给外部宿主机, 在启动镜像时,通过 docker run -v同步宿主和容器之间的文件目录

  • RUN 执行容器中的命令, 可以执行多次

  • CMD 是当容器启动时执行的命令,且Docker中只能使用一次

编写shell文件

#!/bin/bash

cd /usr/src

scrapy crawl guoxue

构建镜像

在执行docker build之前,需要将sh文件改为可执行, 且文件格式改为UNIX。

vi run.sh文件,按shift+:进入命令行,执行以下指令:

:set ff=unix

docker build -t dushu:1.0 .

成功之后,查看镜像是否存在

docker images

启动镜像

docker run -itd --name spider_dushu -v /root/dushu_spider:/usr/src dushu:1.0

查看日志是否启动

cat dushu.log

docker exec spider_dushu cat dushu.log

docker stop spider_dushu

定时器

while循环

crontab

vi /root/runspider.sh

#!/bin/bash

cd /root/spider_dushu

source /root/venvs/dushu/bin/activate

scrapy crawl guoxue

docker start spider_dushu

chmod +x runspider.sh

ln -s /root/runspider.sh /usr/bin/run_dushu

测试命令

run_dushu

编辑定时任务, vi /root/dushu.cron

每半小时(30分)执行一次 run_dushu命令

30 * * * * run_dushu

格式: 分 时 天 月 周

添加定时任务

crontab dushu.cron

crontab -l

查看定时任务是否添加成功

作业

  • 在scrapy框架中如何记录日志信息

spider.logger.info()/error()/warning()/critical()

LOG_LEVEL = ‘INFO’

LOG_FILE = ‘xxx.log’

  • 使用ImagesPipeline时需要注意哪些事项

settings.py

IMAGE_STORE=‘’

Spider类的parse()函数中

item[‘image_urls’]

item[‘images’]

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)
img

ob_id数据,用于停止爬虫。

docker部署

编写Dockerfile文件

FROM 119.3.170.97:5000/ubuntu:latest

MAINTAINER disen 610039018@qq.com

ADD . /usr/src

WORKDIR /usr/src

VOLUME /usr/src

RUN pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple

RUN chmod +x run.sh

CMD /usr/src/run.sh

  • ADD 命令将当前目录下所有文件复制到容器的/usr/src目录下

  • WORKDIR 容器中切换当前的工作目录,类似于cd

  • VOLUME 将容器中的文件位置暴露给外部宿主机, 在启动镜像时,通过 docker run -v同步宿主和容器之间的文件目录

  • RUN 执行容器中的命令, 可以执行多次

  • CMD 是当容器启动时执行的命令,且Docker中只能使用一次

编写shell文件

#!/bin/bash

cd /usr/src

scrapy crawl guoxue

构建镜像

在执行docker build之前,需要将sh文件改为可执行, 且文件格式改为UNIX。

vi run.sh文件,按shift+:进入命令行,执行以下指令:

:set ff=unix

docker build -t dushu:1.0 .

成功之后,查看镜像是否存在

docker images

启动镜像

docker run -itd --name spider_dushu -v /root/dushu_spider:/usr/src dushu:1.0

查看日志是否启动

cat dushu.log

docker exec spider_dushu cat dushu.log

docker stop spider_dushu

定时器

while循环

crontab

vi /root/runspider.sh

#!/bin/bash

cd /root/spider_dushu

source /root/venvs/dushu/bin/activate

scrapy crawl guoxue

docker start spider_dushu

chmod +x runspider.sh

ln -s /root/runspider.sh /usr/bin/run_dushu

测试命令

run_dushu

编辑定时任务, vi /root/dushu.cron

每半小时(30分)执行一次 run_dushu命令

30 * * * * run_dushu

格式: 分 时 天 月 周

添加定时任务

crontab dushu.cron

crontab -l

查看定时任务是否添加成功

作业

  • 在scrapy框架中如何记录日志信息

spider.logger.info()/error()/warning()/critical()

LOG_LEVEL = ‘INFO’

LOG_FILE = ‘xxx.log’

  • 使用ImagesPipeline时需要注意哪些事项

settings.py

IMAGE_STORE=‘’

Spider类的parse()函数中

item[‘image_urls’]

item[‘images’]

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-Q36eZ35u-1712468551330)]
[外链图片转存中…(img-dqfGntXV-1712468551331)]



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)
[外链图片转存中…(img-nDFrCCVu-1712468551331)]

  • 33
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值