两周从爬虫小白变大神,看完你就知道我不是标题党了五万字教程,建议收藏
Posted 五包辣条!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了两周从爬虫小白变大神,看完你就知道我不是标题党了五万字教程,建议收藏相关的知识,希望对你有一定的参考价值。
大家好,我是辣条,今天给大家带来最硬核的爬虫教程。
目录
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-Type
为multipart/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
-
-
买家秀的模特的所有图片, 图片的名称是姓名-序号, 如'Disen-1.jpg', 'Disen-2.jpg'
-
中国图书网
爬虫所有的小说的基本信息(名称、作者、出版社、原价、折扣价、活动标签、 简介)
扩展
-
在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()
-
-
基于Flask实现文件上传服务器, 通过requests测试文件上传接口。
-
优化美女网爬虫,将数据存到es搜索引擎中
-
完成站长之家的多任务爬虫的数据存储(ES引擎/csv)
爬虫第四天
回顾知识点
re正则
-
字符的表示
-
.
任意一个字符, 除了换行 -
[a-f]
范围内的任意一个字符 -
\\w
字母、数字和下划线组成的任意的字符 -
\\W
-
\\d
-
\\D
-
\\s
-
\\S
-
-
量词(数量)表示
-
*
0或多个 -
+
1或多个 -
?
0 或 1 个 -
{n}
n 个 -
{n,}
至少n个 -
{n, m}
n~m个
-
-
分组表示
-
( )
普通的分组表示, 多个正则分组时, search().groups() 返回是元组 -
(?P<name> 字符+数量)
带有名称的分组, 多个正则分组时,search().groupdict()返回是字典, 字典的key即是分组名。import re text = '123abc90ccc' re.search(r'(?P<n1>\\d+?)[a-z]+?(?P<n2>\\d+)', text).groupdict()
-
-
Python中的正则模块
-
re.compile() 一次生成正则对象,可以多次匹配查询
-
re.match(正则对象, 字符串)
-
re.search()
-
re.findall()
-
re.sub()
re.sub('\\d+', '120', text) # 将text中的所有数字替换成120
分享面试题:
给定列表,每一个元组中包含字母和数字, 要求字母和数字分开排序 如: ['abc12', 'abc9', 'abc10', 'ac8', 'ac12'] 排序之后结果是: ['abc9', 'abc10', 'abc12', 'ac8', 'ac12']
def format_number(item): replace_number = re.findall(r'\\d+',item)[0].rjust(2, '0') return re.sub(r'\\d+',replace_number,item) arr =
以上是关于两周从爬虫小白变大神,看完你就知道我不是标题党了五万字教程,建议收藏的主要内容,如果未能解决你的问题,请参考以下文章
CSS,HTML,JS 以及Vue前端面试题八股文总结看完你就变高手
-