两周从爬虫小白变大神,看完你就知道我不是标题党了五万字教程,建议收藏

Posted 五包辣条!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了两周从爬虫小白变大神,看完你就知道我不是标题党了五万字教程,建议收藏相关的知识,希望对你有一定的参考价值。

大家好,我是辣条,今天给大家带来最硬核的爬虫教程。

目录

Python爬虫第一天

什么是爬虫

爬虫与Web后端服务之间的关系

Python爬虫技术的相关库

常见反爬虫的策略

爬虫库urllib【重要】

作业

爬虫第二天

回顾知识点

requests库【重点】

数据解析方式之xpath

绝对路径

相对路径

数据提取

位置条件

属性条件

在Python中应用

作业

爬虫第三天

回顾知识点

requests库

xpath解析

扩展封装ES-SDK

正则解析数据

扩展Linux文件权限

re面试中的问题

作业

爬虫第四天

回顾知识点

re正则

进程和线程

BS4数据解析

协程爬虫

协程的三种方式

协程第三方的框架

动态js渲染

Selenium

Splash

作业

爬虫最五天

回顾知识点

协程的爬虫

Seleinum库

Chrome-headless

Splash渲染

下载镜像

启动镜像

render.html接口

自动化测试

单元测试

集成测试

作业

爬虫第六天

回顾知识点

selenium框架

docker

日志模块进阶

日志格式

日志模块的核心

scrapy框架

scrapy架构组成

scrapy指令

Response类

Request类

作业

爬虫第七天

回顾知识点

scrapy框架

scrapy数据管道

指令方式存储

Pipeline

定量爬虫

基于信号方式

下载中间件

爬虫中间件

下载中间件 [重点]

作业

爬虫第八天

回顾知识点

数据处理

中间件

规则爬虫

规则爬虫【重】

LinkExtractor 类

核心的类

图片管道

使用ImagesPipeline

自定义ImagesPipeline

其它技术点

日志

post请求

Selenium中间件

作业

爬虫第九天

回顾知识点

Selenium下载中间件

分布式爬虫

什么是分布式

常见消息队列

scrapy-redis

爬虫程序部署

scrapyd

docker部署

作业

爬虫第十天

回顾爬虫技术

网络请求

数据解析

数据存储

爬虫框架

mongodb

docker部署

数据结构

常用操作

作业


Python爬虫第一天

学习内容:

  • 什么是爬虫(Spider)

  • 爬虫与Web后端服务之间的关系

  • Python爬虫技术的相关库

  • 常见反爬虫的策略

  • 爬虫库urllib【重要】

什么是爬虫

爬虫Spider的概念

爬虫用于爬取数据, 又称之为数据采集程序

爬取的数据来源于网络,网络中的数据可以是由Web服务器nginx/Apache)、数据库服务器(mysql、Redis)、索引库(ElastichSearch)、大数据(Hbase/Hive)、视频/图片库(FTP)、云存储等(OSS)提供的。

爬取的数据是公开的、非盈利的。

Python爬虫

使用Python编写的爬虫脚本(程序)可以完成定时、定量、指定目标(Web站点)的数据爬取。主要使用多(单)线程/进程、网络请求库、数据解析、数据存储、任务调度等相关技术。

Python爬虫工程师,可以完成接口测试、功能性测试、性能测试和集成测试。

爬虫与Web后端服务之间的关系

爬虫使用网络请求库,相当于客户端请求, Web后端服务根据请求响应数据。

爬虫即向Web服务器发起HTTP请求,正确地接收响应数据,然后根据数据的类型(Content-Type)进行数据的解析及存储。

爬虫程序在发起请求前,需要伪造浏览器(User-Agent指定请求头),然后再向服务器发起请求, 响应200的成功率高很多。

Python爬虫技术的相关库

网络请求:

  • urllib

  • requests / urllib3

  • selenium(UI自动测试、动态js渲染)

  • appium(手机App 的爬虫或UI测试)

数据解析:

  • re正则

  • xpath

  • bs4

  • json

数据存储:

  • pymysql

  • mongodb

  • elasticsearch

多任务库:

  • 多线程 (threading)、线程队列 queue

  • 协程(asynio、 gevent/eventlet)

爬虫框架

  • scrapy

  • scrapy-redis 分布式(多机爬虫)

常见反爬虫的策略

  • UA(User-Agent)策略

  • 登录限制(Cookie)策略

  • 请求频次(IP代理)策略

  • 验证码(图片-云打码,文字或物件图片选择、滑块)策略

  • 动态js(Selenium/Splash/api接口)策略

爬虫库urllib【重要】

urllib.request模块

简单的请求

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">from</span> <span style="color:#000000">urllib</span>.<span style="color:#000000">request</span> <span style="color:#770088">import</span> <span style="color:#000000">urlopen</span>
​
<span style="color:#aa5500"># 发起网络请求</span>
<span style="color:#000000">resp</span> = <span style="color:#000000">urllopen</span>(<span style="color:#aa1111">'http://www.hao123.com'</span>)
<span style="color:#770088">assert</span> <span style="color:#000000">resp</span>.<span style="color:#000000">code</span> == <span style="color:#116644">200</span>
<span style="color:#3300aa">print</span>(<span style="color:#aa1111">'请求成功'</span>)
<span style="color:#aa5500"># 保存请求的网页</span>
<span style="color:#aa5500"># f 变量接收open()函数返回的对象的__enter__()返回结果</span>
<span style="color:#770088">with</span> <span style="color:#3300aa">open</span>(<span style="color:#aa1111">'a.html'</span>, <span style="color:#aa1111">'wb'</span>) <span style="color:#770088">as</span> <span style="color:#000000">f</span>:
     <span style="color:#000000">f</span>.<span style="color:#000000">write</span>(<span style="color:#000000">resp</span>.<span style="color:#000000">read</span>())</span></span>

urlopen(url, data=None)可以直接发起url的请求, 如果data不为空时,则默认是POST请求,反之为GET请求。

resp是http.client.HTTPResponse类对象。

带请求头的请求

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">from</span> <span style="color:#000000">urllib</span>.<span style="color:#000000">request</span> <span style="color:#770088">import</span> <span style="color:#000000">Request</span>
​
<span style="color:#770088">def</span> <span style="color:#0000ff">search_baidu</span>():
    <span style="color:#aa5500"># 网络资源的接口(URL)</span>
    <span style="color:#000000">url</span> = <span style="color:#aa1111">'https://www.baidu.com'</span>
​
    <span style="color:#aa5500"># 生成请求对象,封装请求的url和头header</span>
    <span style="color:#000000">request</span> = <span style="color:#000000">Request</span>(<span style="color:#000000">url</span>,
                      <span style="color:#000000">headers</span>={
                          <span style="color:#aa1111">'Cookie'</span>: <span style="color:#aa1111">'BIDUPSID=16CECBB89822E3A2F26ECB8FC695AFE0; PSTM=1572182457; BAIDUID=16CECBB89822E3A2C554637A8C5F6E91:FG=1; BD_UPN=123253; H_PS_PSSID=1435_21084_30211_30283; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; H_PS_645EC=6f7aTIObS%2BijtMmWgFQxMF6H%2FhK%2FcpddiytCBDrefRYyFX%2B%2BTpyRMZInx3E'</span>,
                          <span style="color:#aa1111">'User-Agent'</span>: <span style="color:#aa1111">'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'</span>
                      })
​
    <span style="color:#000000">response</span> = <span style="color:#000000">urlopen</span>(<span style="color:#000000">request</span>)  <span style="color:#aa5500"># 发起请求</span>
​
    <span style="color:#770088">assert</span> <span style="color:#000000">response</span>.<span style="color:#000000">code</span> == <span style="color:#116644">200</span>
    <span style="color:#3300aa">print</span>(<span style="color:#aa1111">'请求成功'</span>)
​
    <span style="color:#aa5500"># 读取响应的数据</span>
    <span style="color:#000000">bytes_</span> = <span style="color:#000000">response</span>.<span style="color:#000000">read</span>()
    
    <span style="color:#aa5500"># 将响应的数据写入文件中</span>
    <span style="color:#770088">with</span> <span style="color:#3300aa">open</span>(<span style="color:#aa1111">'index.html'</span>, <span style="color:#aa1111">'wb'</span>) <span style="color:#770088">as</span> <span style="color:#000000">file</span>:
        <span style="color:#000000">file</span>.<span style="color:#000000">write</span>(<span style="color:#000000">bytes_</span>)</span></span>

任务1:收集Http协议的报文头的哪些Key

urllib.parse模块

此模块有两个核心的函数:

  • quote() 仅对中文字符串进行url编码;

  • urlencode() 可以针对一个字典中所有的values进行编码,然后转成key=value&key=value的字符串。

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#aa1111">"""</span>
<span style="color:#aa1111">复杂的GET请求,多页面请求下载</span>
<span style="color:#aa1111">"""</span>
<span style="color:#770088">from</span> <span style="color:#000000">urllib</span>.<span style="color:#000000">request</span> <span style="color:#770088">import</span> <span style="color:#000000">Request</span>, <span style="color:#000000">urlopen</span>
<span style="color:#770088">from</span> <span style="color:#000000">urllib</span>.<span style="color:#000000">parse</span> <span style="color:#770088">import</span> <span style="color:#000000">urlencode</span>
​
<span style="color:#770088">import</span> <span style="color:#000000">ssl</span>
​
<span style="color:#770088">import</span> <span style="color:#000000">time</span>
​
<span style="color:#000000">ssl</span>.<span style="color:#000000">_create_default_https_context</span> = <span style="color:#000000">ssl</span>.<span style="color:#000000">_create_unverified_context</span>
​
<span style="color:#000000">url</span> = <span style="color:#aa1111">'https://www.baidu.com/s?'</span>
​
<span style="color:#000000">headers</span> = {
    <span style="color:#aa1111">'User-Agent'</span>: <span style="color:#aa1111">'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'</span>,
    <span style="color:#aa1111">'Cookie'</span>: <span style="color:#aa1111">'BIDUPSID=16CECBB89822E3A2F26ECB8FC695AFE0; PSTM=1572182457; BAIDUID=16CECBB89822E3A2C554637A8C5F6E91:FG=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1573184257; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; H_PS_PSSID=1435_21084_30211_30283; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; delPer=0; PSINO=1; to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; APPGUIDE_8_2_2=1; yjs_js_security_passport=0927713bf2c240ca607108086d07729426db4dbb_1577084843_js; __yjsv5_shitong=1.0_7_c3620451e4363f4aed30cbe954abf8942810_300_1577084847314_223.255.14.197_2d7151e0; from_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D'</span>,
    <span style="color:#aa1111">'x-requested-with'</span>: <span style="color:#aa1111">'XMLHttpRequest'</span>
}
​
<span style="color:#000000">params</span> = {
    <span style="color:#aa1111">'wd'</span>: <span style="color:#aa1111">''</span>,
    <span style="color:#aa1111">'pn'</span>: <span style="color:#116644">0</span>  <span style="color:#aa5500"># 0, 10, 20, 30 ...  = (n-1)*10</span>
}
​
<span style="color:#770088">def</span> <span style="color:#0000ff">pages_get</span>(<span style="color:#000000">wd</span>):
    <span style="color:#000000">params</span>[<span style="color:#aa1111">'wd'</span>] = <span style="color:#000000">wd</span>
    <span style="color:#770088">for</span> <span style="color:#000000">page</span> <span style="color:#770088">in</span> <span style="color:#3300aa">range</span>(<span style="color:#116644">1</span>, <span style="color:#116644">101</span>):
        <span style="color:#000000">params</span>[<span style="color:#aa1111">'pn'</span>] = (<span style="color:#000000">page</span><span style="color:#981a1a">-</span><span style="color:#116644">1</span>)<span style="color:#981a1a">*</span><span style="color:#116644">10</span>
​
        <span style="color:#000000">page_url</span> = <span style="color:#000000">url</span><span style="color:#981a1a">+</span><span style="color:#000000">urlencode</span>(<span style="color:#000000">params</span>)
        <span style="color:#000000">resp</span> = <span style="color:#000000">urlopen</span>(<span style="color:#000000">Request</span>(<span style="color:#000000">page_url</span>,
                               <span style="color:#000000">headers</span>=<span style="color:#000000">headers</span>))
​
        <span style="color:#770088">assert</span> <span style="color:#000000">resp</span>.<span style="color:#000000">code</span> == <span style="color:#116644">200</span>
        <span style="color:#000000">file_name</span> = <span style="color:#aa1111">'baidu_pages/%s-%s.html'</span> <span style="color:#981a1a">%</span> (<span style="color:#000000">wd</span>, <span style="color:#000000">page</span>)
        <span style="color:#770088">with</span> <span style="color:#3300aa">open</span>(<span style="color:#000000">file_name</span>, <span style="color:#aa1111">'wb'</span>) <span style="color:#770088">as</span> <span style="color:#000000">f</span>:
            <span style="color:#000000">bytes_</span> = <span style="color:#000000">resp</span>.<span style="color:#000000">read</span>()
            <span style="color:#000000">f</span>.<span style="color:#000000">write</span>(<span style="color:#000000">bytes_</span>)
            <span style="color:#3300aa">print</span>(<span style="color:#aa1111">f'{file_name} 写入成功!'</span>)
            <span style="color:#000000">time</span>.<span style="color:#000000">sleep</span>(<span style="color:#116644">0.5</span>)
​
    <span style="color:#3300aa">print</span>(<span style="color:#aa1111">'下载 %s 100页成功!'</span> <span style="color:#981a1a">%</span> <span style="color:#000000">wd</span>)
​
​
<span style="color:#770088">if</span> <span style="color:#000000">__name__</span> == <span style="color:#aa1111">'__main__'</span>:
    <span style="color:#000000">pages_get</span>(<span style="color:#aa1111">'Python3.6'</span>)</span></span>

HTTP处理器

urllib的请求处理器,主要用于urllib.request.build_opener()函数参数,表示构造一个由不同处理组成的伪浏览器。

HTTPHandler

处理Http协议的请求处理。

5HTTPCookieProcessor

处理Cookie的处理器,创建类实例时,需要提供http.cookiejar.CookieJar类的实例对象。

ProxyHandler

作业

  • 写出Python上下文的两个核心函数

    <span style="background-color:#f8f8f8"><span style="color:#000000">__enter__</span>(<span style="color:#0055aa">self</span>)
    <span style="color:#000000">__exit__</span>(<span style="color:#0055aa">self</span>, <span style="color:#000000">except_type</span>, <span style="color:#000000">except_value</span>, <span style="color:#000000">except_tb</span>)</span>

  • 写出正则中的(), [] , {} 三个符号的作用

    <span style="background-color:#f8f8f8">( ) 用于分组的符号
    [ ] 指定匹配字符的范围,如 [a-c_B-F]
    { } 指定匹配的长度(量词表示)</span>

  • 写出pymysql.Connect()连接数据库的核心参数

    <span style="background-color:#f8f8f8"><span style="color:#000000">Connect</span>(<span style="color:#000000">host</span>,
                    <span style="color:#000000">port</span>=<span style="color:#116644">3306</span>,
            <span style="color:#000000">user</span>,
            <span style="color:#000000">password</span>,
            <span style="color:#000000">db</span>,
            <span style="color:#000000">charset</span>)</span>

  • 豆瓣动作电影排行榜

  • 肯德基店铺位置

爬虫第二天

回顾知识点

核心的网络请求库 -> urllib库

  • urllib.request 模块

    • urlopen(url | request: Request, data=None) data是bytes类型

    • urlretrieve(url, filename) 下载url的资源到指定的文件

    • build_opener(*handlder) 构造浏览器对象

      • opener.open(url|request, data=None) 发起请求

    • Request 构造请求的类

    data={
      'wd': ''
    }
    # urlencode(data)  => 'wd=%f5%e6%e6%f5%e6%e6'
    request = Request(url, data=urlencode(data).encode())
    • HTTPHandler HTTP协议请求处理器

    • ProxyHandler(proxies={'http': 'http://proxy_ip:port'}) 代理处理

    • HTTPCookieProcessor(CookieJar())

      • http.cookiejar.CookieJar 类

  • urllib.parse模块

    • quote(txt) 将中文字符串转成url编码

    • urlencode(query: dict) 将参数的字典转成url编码,结果是key=value&key=value形式,即以 application/x-www-form-urlencoded作为url编码类型。

requests库【重点】

requests库也是一个网络请求库, 基于urllib和urllib3封装的便捷使用的网络请求库。

安装环境

pip install requests -i https://mirrors.aliyun.com/pypi/simple

核心的函数

  • requests.request() 所有请求方法的基本方法

    以下是request()方法的参数说明

    • method: str 指定请求方法, GET, POST, PUT, DELETE

    • url: str 请求的资源接口(API),在RESTful规范中即是URI(统一资源标签识符)

    • params: dict , 用于GET请求的查询参数(Query String params);

    • data: dict , 用于POST/PUT/DELETE 请求的表单参数(Form Data)

    • json: dict 用于上传json数据的参数, 封装到body(请求体)中。请求头的Content-Type默认设置为application/json

    • files: dict, 结构 {'name': file-like-object | tuple}, 如果是tuple, 则有三种情况:

      • ('filename', file-like-object)

      • ('filename', file-like-object, content_type)

      • ('filename', file-like-object, content_type, custom-headers)

      指定files用于上传文件, 一般使用post请求,默认请求头的Content-Typemultipart/form-data类型。

    • headers/cookies : dict

    • proxies: dict , 设置代理

    • auth: tuple , 用于授权的用户名和口令, 形式('username', 'pwd')

  • requests.get() 发起GET请求, 查询数据

    可用参数:

    • url

    • params

    • json

    • headers/cookies/auth

  • requests.post() 发起POST请求, 上传/添加数据

    可用参数:

    • url

    • data/files

    • json

    • headers/cookies/auth

  • requests.put() 发起PUT请求, 修改或更新数据

  • requests.patch() HTTP幂等性的问题,可能会出现重复处理, 不建议使用。用于更新数据

  • requests.delete() 发起DELETE请求,删除数据

requests.Respose

以上的请求方法返回的对象类型是Response, 对象常用的属性如下:

  • status_code 响应状态码

  • url 请求的url

  • headers : dict 响应的头, 相对于urllib的响应对象的getheaders(),但不包含cookie。

  • cookies: 可迭代的对象,元素是Cookie类对象(name, value, path)

  • text : 响应的文本信息

  • content: 响应的字节数据

  • encoding: 响应数据的编码字符集, 如utf-8, gbk, gb2312

  • json(): 如果响应数据类型为application/json,则将响应的数据进行反序化成python的list或dict对象。

    • 扩展-javascript的序列化和反序列化

      • JSON.stringify(obj) 序列化

      • JSON.parse(text) 反序列化

数据解析方式之xpath

xpath属于xml/html解析数据的一种方式, 基于元素(Element)的树形结构(Node > Element)。选择某一元素时,根据元素的路径选择,如 /html/head/title获取<title>标签。

绝对路径

从根标签开始,按tree结构依次向下查询。

如 /html/body/table/tbody/tr。

相对路径

相对路径可以有以下写法

  • 相对于整个文档

    //img

    查找出文档中所有的<img>标签元素

  • 相对于当前节点

    //table

    假如当前节点是<table>, 查找它的<img>的路径的写法

    .//img

数据提取

  • 提取文本

    //title/text()
  • 提取属性

    //img/@href

位置条件

获取网页中的数据类型与字符集, 获取第一个<meta>标签

//meta[1]//@content

获取最后一个<meta>标签

//meta[last()]//@content

获取倒数第二个<meta>标签

//meta[position()-2]//@content

获取前三个<meta>标签

//meta[position()<3]//@content

属性条件

查找 class为circle-img<img>标签

//img[@class="circle-img"]

在Python中应用

安装包 pip install lxml

作业

  • 写出urllib库的请求处理器有哪些类(尽量写全路径)

    • urllib.request.HTTPHandler

    • urllib.request.HTTPCookieProcessor

    • urllib.request.ProxyHandler

  • 写出json.loads()和pickle.loads()返回的数据类型

    • json.loads() 返回list或dict, 加载的是字符串

    • pickle.loads() 返回是python中的对象, 加载的是字节数组 bytes

  • 写出pymysql的cursor.execute()方法中的参数及作用

    • 有两个参数, 一个是sql, 一个是args

    • args可以是tuple,对应sql字符串的 %s

    • args也可以是dict, 对应sql字符串的%(xxx)s, xxx是dict中的key

  1. 买家秀的模特的所有图片, 图片的名称是姓名-序号, 如'Disen-1.jpg', 'Disen-2.jpg'

  2. 中国图书网

    爬虫所有的小说的基本信息(名称、作者、出版社、原价、折扣价、活动标签、 简介)

扩展

  • 在Ubuntu 下安装docker

  • 基于docker部署ElasticSearch搜索引擎库。

  • 基于requests实现索引库及文档的添加和查询。

爬虫第三天

回顾知识点

requests库

  • requests.request(method, url, **kwargs)

    常用的参数

    • params/data/json 上传数据

    • files 上传文件

    • headers/cookies

    • proxies 代理服务器

    • auth 授权

  • requests.get(url, params, **kwargs)

  • requtests.post(url, data, json, **kwargs)

  • requests.put(url, data, json, **kwargs)

  • requests.delete(url, **kwargs)

  • requests.session() - > session对象, 可以调用 s.get()/post()/put()/delete()等方法,多次请求的会话(连接Session)是同一个

所有的请求返回的对象是requests.Response类的实例, 实例的属性:

  • status_code

  • headers

  • encoding

  • text/content

  • cookies

  • json() 反序列化json文本字符串为python的list或dict的对象

xpath解析

  • 路径写法

    • / 依次查找

    • // 间接查找

    • ./ 从当前元素下查找

    • .// 从当前元素的间接子节点查找

  • 位置条件

    • //li[1] 整个文档中的第一个<li>标签

    • //li[last()] 最后一个

    • //li[position() < 3] 前2个

    • //li[position() - 2] 倒数第2个

  • 属性条件

    • //li[@id="xxxx"]

    • //li[@class=""] @class 属性名

    • //li[@class="" and @name=""] 多个属性的且的关系

  • 同时提取两个元素

    • //title/text() | //img/@src

  • 模糊条件

    • //div[contains(@class, "page")] 查找class属性包含page的所有div标签

    • //div[starts-with(@class, "box")] 第一个class的属性值为box的div标签

    • //div[ends-with(@class, "clearfix")]最一个class的属性值为clearfix的div标签

扩展封装ES-SDK

"""
基于requests库封装操作ElasticSearch搜索引擎的函数 (SDK)
"""
from urllib.parse import quote
​
import requests
​
INDEX_HOST = '119.3.170.97'
INDEX_PORT = 80
​
​
class ESIndex():
    """ES的索引库的类"""
​
    def __init__(self, index_name, doc_type):
        self.index_name = index_name
        self.doc_type = doc_type
​
    def create(self):  # 创建索引库
        url = f'http://{INDEX_HOST}:{INDEX_PORT}/{self.index_name}'
        json_data = {
            "settings": {
                "number_of_shards": 5,
                "number_of_replicas": 1
            }
        }
        resp = requests.put(url, json=json_data)
        if resp.status_code == 200:
            print('创建索引成功')
            print(resp.json())
​
    def delete(self):  # 删除索引库
        resp = requests.delete(f'http://{INDEX_HOST}:{INDEX_PORT}/{self.index_name}')
        if resp.status_code == 200:
            print('delete index ok')
​
    def add_doc(self, item: dict):
        # 向库中增加文档
        doc_id = item.pop('id', None)
        url = f'http://{INDEX_HOST}:{INDEX_PORT}/{self.index_name}/{self.doc_type}/'
        if doc_id:
            url += str(doc_id)
​
        resp = requests.post(url, json=item)
        if resp.status_code == 200:
            print(f'{url} 文档增加成功!')
​
    def remove_doc(self, doc_id):
        # 删除文档
        url = f'http://{INDEX_HOST}:{INDEX_PORT}/{self.index_name}/{self.doc_type}/{doc_id}'
        resp = requests.delete(url)
        if resp.status_code == 200:
            print(f'delete {url} ok')
​
    def update_doc(self, item: dict):
        # 更新文档
        doc_id = item.pop('id')
        url = f'http://{INDEX_HOST}:{INDEX_PORT}/{self.index_name}/{self.doc_type}/{doc_id}'
        resp = requests.put(url, json=item)
        assert resp.status_code == 200
        print(f'{url} update ok')
​
    def query(self, wd=None):
        # 查询
        q = quote(wd) if wd else ''
        url = f'http://{INDEX_HOST}:{INDEX_PORT}/{self.index_name}/_search?size=100'
        if q:
            url += f'&q={q}'
        resp = requests.get(url)
        datas = []
        if resp.status_code == 200:
            ret = resp.json()
            hits = ret['hits']['hits']
            if hits:
                for item in hits:
                    data = item['_source']
                    data['id'] = item['_id']
​
                    datas.append(data)
​
        return datas
​
​
if __name__ == '__main__':
    index = ESIndex('gushiwen', 'tuijian')
    # index.create()
    # index.add_doc({
    #     'id': 1,
    #     'name': 'disen',
    #     'price': 19.5
    # })
    #
    # index.add_doc({
    #     'id': 2,
    #     'name': 'jack',
    #     'price': 10.5
    # })
​
    print(index.query())

正则解析数据

扩展Linux文件权限

100  ->4 -> r
​
010 -> 2-> w
​
001 -> 1 -> x
​
​
​
100 | 010 = 110  # 增加权限
​
110 & 100 == 100  # 验证100权限
​
110 ^ 100 = 010   # 删除100权限 

re面试中的问题

  • compile() /match()/search() 三者之间的区别

  • search()/findall()区别

  • 贪婪模式和非贪婪模式

解析站长之家

"""
基于正则re模块解析数据
"""
import re
import os
​
import requests
​
from utils.header import get_ua
​
base_url = 'http://sc.chinaz.com/tupian/'
url = f'{base_url}shuaigetupian.html'
​
headers = {
    'User-Agent': get_ua()
}
​
if os.path.exists('mn.html'):
    with open('mn.html', encoding='utf-8') as f:
        html = f.read()
else:
    resp = requests.get(url, headers=headers)
    print(resp.encoding)  # ios-8859-1
    resp.encoding = 'utf-8'  # 可以修改响应的状态码
    assert resp.status_code == 200
    html = resp.text
    with open('mn.html', 'w', encoding=resp.encoding) as f:
        f.write(html)
​
# print(html)
#  [\\u4e00-\\u9fa5]
compile = re.compile(r'<img src2="(.*?)" alt="(.*?)">')
compile2 = re.compile(r'<img alt="(.*?)" src="(.*?)">')
​
imgs = compile.findall(html)  # 返回list
if len(imgs) == 0:
    imgs = compile2.findall(html)
​
print(len(imgs), imgs, sep='\\n')
​
# 下一页
next_url = re.findall(r'<b>20</b></a><a href="(.*?)" class="nextpage"',html, re.S)
​
print(base_url+next_url[0])

作业

  • 写出requests.request()方法常用的参数及参数类型

    • method: str 请求方法, 可以指定 get, post, put, delete, options

    • url : str 请求路径或api接口

    • params/data/json : dict 上传的请求参数及json或form的data数据

    • headers/cookie: dict 请求头或Cookie信息

    • files: dict 上传的文件信息

  • 写出正则的贪婪模式有哪些

    • .* 0或多个任意字符

    • .+ 1或多个任意字符

    • .?

    • .{n, } 至少n个以上的任意字符

    • .{n, m} 至少n个以上的任意字符

  • 写出str对象的常用方法(10+)

    • join()

    • split()

    • strip()

    • replace()

    • upper()

    • lower()

    • title()

    • index()/rindex()

    • find()/rfind()

    • insert()

    • just()/ljust()/rjust()

    • capitalize() # 每个单词的首字母大写

      要求: 自动生成订单号
      订单号的格式: 20191226000001
      当天的单号按自增,第二天的序号是从1开始。
    • count()

    • encode()

    • startswith()/endswith()

    • format()

  1. 基于Flask实现文件上传服务器, 通过requests测试文件上传接口。

  2. 优化美女网爬虫,将数据存到es搜索引擎中

  3. 完成站长之家的多任务爬虫的数据存储(ES引擎/csv)

爬虫第四天

回顾知识点

re正则