爬虫相关知识点

爬虫相关知识点

  • 什么是爬虫?
  • 爬虫与web后端服务之间的关系
  • Python爬虫技术的相关库
  • 常见反爬虫策略
  • 爬虫库urlib [重点]

一、什么是爬虫?

1.1 爬虫spider的概念

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

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

爬虫的数据是公开的,非盈利目的。

1.2 Python爬虫

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

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

二、爬虫与web后端服务之间的关系

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

数据。

爬虫向服务器发起http请求,正确的接受响应数据,然后根据数据的

类型(Content-Type)进行数据的解析及存储。

爬虫程序发起请求前,需要伪造浏览器(User-Agent指定请求头)

然后再向服务器发起请求,响应200的成功率高很多。

http报文格式

三、Python爬虫技术的相关库

网络请求:

  • urlib(urllib2和urllib3)
  • requests
  • selenium(UI自动测试,动态json渲染)
  • appium(手机app应用的爬虫或者UI测试)

数据解析:

  • re正则
  • xpath
  • bs4
  • json

数据存储:

  • pymysql
  • mongodb
  • elasticsearch

多任务库:

  • 多线程(threading)、线程队列(queue)
  • 协程(asynio、gevent/evevtlet)

爬虫框架:

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

四、常见反爬虫策略

UA ( User-Agent ) 策略

登录限制(Cookie)策略

请求频次(IP代理)策略

验证码( 图片-云打码、文字或物品图片选择、滑块)

动态json(selenuim/Splash/Api接口)策略

五、爬虫库urllib [重点]

5.1 urllib .resquest模块

5.1.1 简单的请求
from  urllib.request import urlopen
#发起网络请求
resp = urlopen('https://www.hao123.com')    
assert response.code == 200
print('请求成功')
#保存请求的网页
# f 变量接收open()函数返回的对象的_enter_()返回结果
with open'a.html','wb'as f:
    f.write(resp.read())

urlopen(url,data=None)可以直接发起url的请求,如果data不为空时,

则默认是POST请求,反之为GET请求。

resp是https.client.HTTPResponse类对象。

5.1.2 带请求头的请求

def search_baidu_(wd='阿'):
    url = 'https://www.baidu.com/s?wd=%s'
    #生成请求对象,封装请求url和头header
    request =Request(url % quote(wd),
                     headers={
                         'Cookie':'BIDUPSID=A6FA40249A7FDACA204C353784FBF5FD; PSTM=1647777387; BAIDUID=A6FA40249A7FDACA4031F9E78BFED697:FG=1; ' 'BAIDUID_BFESS=F0371DF47B0B464C295F844A241C697B:FG=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BA_HECTOR=agah24al0k850h84fq1h4lojf0r;'
                                  ' H_PS_PSSID=36069_36174_31254_36020_36004_36167_34584_36140_36120_36193_36073_35802_26350_35870_36092_36061',
                        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, '
                                      'like Gecko) Chrome/100.0.4896.60 Safari/537.36'

                     })
    response = urlopen(request)    #发起请求
    assert response.code == 200
    print('请求成功')
    #读取响应数据
    bytes_ = response.read()
    
    #将响应的数据写入文件中
    with open('%s.html' %wd,'wb') as file:
        file.write(bytes_)

5.2 urllib.parse模块

  • quote()仅对中文字=字符串进行编码;
  • urlencode()可以针对一个字典中所有的values进行编码,然后转成key=value&key=value的字符串。
#spider01_urllib.py (爬取成功)
'''

初次使用urllib实现爬虫的数据请求
urllib.request.urlopen(url) 发起get请求
urllib.request.quote() 将中文进行url编码
urllib.request.urlretrieve(url,filename) 下载url保存filename
'''
from urllib.request import urlopen, urlretrieve, Request
from urllib.parse import quote
import ssl


ssl._create_default_https_context = ssl._create_unverified_context

def search_baidu_(wd='阿'):
    url = 'https://www.baidu.com/s?wd=%s'
    #生成请求对象,封装请求url和头header
    request =Request(url % quote(wd),
                     headers={
                         'Cookie':'BIDUPSID=A6FA40249A7FDACA204C353784FBF5FD; PSTM=1647777387; BAIDUID=A6FA40249A7FDACA4031F9E78BFED697:FG=1; ' 'BAIDUID_BFESS=F0371DF47B0B464C295F844A241C697B:FG=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BA_HECTOR=agah24al0k850h84fq1h4lojf0r;'
                                  ' H_PS_PSSID=36069_36174_31254_36020_36004_36167_34584_36140_36120_36193_36073_35802_26350_35870_36092_36061',
                        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, '
                                      'like Gecko) Chrome/100.0.4896.60 Safari/537.36'

                     })
    response = urlopen(request)    #发起请求
    assert response.code == 200
    print('请求成功')
    #读取响应数据
    bytes_ = response.read()
    #?? 当对象进入上下文时,调用对象的哪个方法
    #?? 当对象退出上下文时,调用对象的哪个方法
    with open('%s.html' %wd,'wb') as file:
        file.write(bytes_)
# def download_image(url):
#     # 从url中获取文件名
#     filename = url[url.rfind('/')+1:]
#     req = Request(url,headers={
#
#         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, '
#                       'like Gecko) Chrome/100.0.4896.60 Safari/537.36'
#
#     })
#
#     urlretrieve(url,filename)
#     resp = urlopen(req)
#     with open (filename,'wb') as file:
#         file.write(resp.read())
#
#     print(f'下载{filename} ok!')


def download_image(url):
    #从url中获取文件名
    filename = url[url.rfind('/')+1:]
    req = Request(url,headers={

        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, '
                      'like Gecko) Chrome/100.0.4896.60 Safari/537.36'

    })

    urlretrieve(url,filename) #只能下载简单html文件


if  __name__ == '__main__':
    # search_baidu_()
    # download_image('https://m.dytt8.net/html/gndy/jddy/20220327/62454.html')
    # download_image('https://img9.doubanio.com/view/photo/l_ratio_poster/public/p2708481820.jpg')
#spider02_urllib_parse.py  (数据包参数和结构和视频里的不同,不知道如何爬取参数,代码直接按照视频里的敲的)
"""
应用 :百度翻译
- urllib.request.Request
- urllib.resquest.urlopen()
- urllib.parse.urlencode()
- 发起 post 请求
"""
import json
from urllib.request import Request, urlopen
from urllib.parse import urlencode

url = 'https://fanyi.baidu.com/sug'  # 请求API接口
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0",
    "Cookie": "BAIDUID=67CDE4542962E31A5515AF1A7D37CC19:FG=1; BIDUPSID=36B360392903B350B056DC11FBD595D5; PSTM=1648979131; BA_HECTOR=2h200g01248l0h2h991h4qjvk0r; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; BDRCVFR[gltLrB7qNCt]=mk3SLVN4HKm; delPer=0; PSINO=7; "
              "H_PS_PSSID=36068_36175_31254_36020_36005_35913_36167_34584_36144_36120_35978_36125_36234_26350_36061; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1649233910; ""Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1649234228; REALTIME_TRANS_SWITCH=1; "
              "FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; APPGUIDE_10_0_2=1; "
              "ab_sr=1.0.1_M2U0NWY1NjE2MTFhZmM1MzdlYWZiNWM5N2Y2YmEzMGNhMjE5YjExOTE0N2YxYzM0MTM5YzY0NDNhMzcyYjFmMjlhOTU0N2NlZDY3YWExNzA4M2RhZTBmYTQxMGI4ZTcwY2IzYWY1NTc2MjAzZDJkNWVmOTRkMTg3NzFiYzAzNDFjMTYyMWM5NmU2NjJiZDNhN2U4NmUwZTYzNmNiNDRmYQ=="
    ,
    "X-Requested-With": "XMLHttpRequest"

}


def fanyi(kw):
    data = {
        'kw': kw
    }

    # Request() 中的data参数是byte类型
    # data 不为空时,是post 请求
    req = Request(url, data=urlencode(data).encode('utf-8'))
    resp = urlopen(req)
    assert resp.code == 200

    json_data = resp.read()  # byte
    content_encode = resp.getheader('Content-Type')
    content_encode = 'utf-8' if content_encode is None else content_encode.split('='[-1])

    return json.loads(json_data.decode(content_encode))


if __name__ == '__main__':
    print(fanyi('orange'))

#spider03_urllib_pages (爬取成功)
"""
复杂GET请求,多页面请求下载
"""
import time
from urllib.request import Request,urlopen
from urllib.parse import urlencode
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

url ='https://www.baidu.com/s?'
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0",
    "Cookie": "BAIDUID=67CDE4542962E31A5515AF1A7D37CC19:FG=1; BIDUPSID=36B360392903B350B056DC11FBD595D5; PSTM=1648979131; BA_HECTOR=2h200g01248l0h2h991h4qjvk0r; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; BDRCVFR[gltLrB7qNCt]=mk3SLVN4HKm; delPer=0; PSINO=7; ""H_PS_PSSID=36068_36175_31254_36020_36005_35913_36167_34584_36144_36120_35978_36125_36234_26350_36061; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1649233910; ""Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1649234228; REALTIME_TRANS_SWITCH=1; ""FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; APPGUIDE_10_0_2=1; ""ab_sr=1.0.1_M2U0NWY1NjE2MTFhZmM1MzdlYWZiNWM5N2Y2YmEzMGNhMjE5YjExOTE0N2YxYzM0MTM5YzY0NDNhMzcyYjFmMjlhOTU0N2NlZDY3YWExNzA4M2RhZTBmYTQxMGI4ZTcwY2IzYWY1NTc2MjAzZDJkNWVmOTRkMTg3NzFiYzAzNDFjMTYyMWM5NmU2NjJiZDNhN2U4NmUwZTYzNmNiNDRmYQ==",
    "X-Requested-With": "XMLHttpRequest"

}
params = {
    'wd': '' ,
    'pn': 0 # 0,10,20,30,... =(n-1)*10
}
def pages_get(wd):
    params['wd']=wd
    for page in range(1,11):
        params['pn'] = (page-1)*10
        page_url = url+urlencode(params)
        resp = urlopen(Request(page_url,
                               headers=headers))
        assert resp.code ==  200
        file_name = 'baidu_pages/%s-%s.html' %(wd,page)
        with open(file_name,'wb') as f :
            bytes_ = resp.read()
            f.write(bytes_)
            print(f'{file_name}  写入成功!')
            time.sleep(0.5)

    print('下载%s 10页成功!' % wd)


if __name__ == '__main__':
    pages_get('Python3.9')

5.3 HTTP处理器

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

5.3.1 HTTPHandler

处理Http协议的请求处理。

5.3.2 HTTPCookieProcessor

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

5.3.3 ProxyHandler

代理设置

其他

Python上下文的两个核心函数

__enter__(self)
__exit__(self, except_type, except_value, except_tb)

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

( ) 用于分组的符号
[ ] 指定匹配字符的范围,如 [a-c_B-F]
{ } 指定匹配的长度(量词表示)

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

Connect(host,
				port=3306,
        user,
        password,
        db,
        charset)

一、Python上下文

1.1什么是上下文

任意的Python对象都可以使用上下文环境,使用with关键字。上下文是任意代码片段的区域,当对象进入上下文环境时,解释器会调用对象的__enter__(),当对象退出上下文环境时,会调用对象的__exit__()

1.2为什么使用

对象在使用上下文环境时,为了确保对象正确的释放资源,避免出现**内存遗漏**。

存在以下对象经常使用上下文with:

  • 文件操作对象open()
  • 数据库的连接conn
  • 线程锁Lock
1.3如何使用
1.3.1重写类的方法

上下文的两个核心方法

class A:
    def go():
        print('up')
	def __enter__(self):
		#进入上下文时,被调用
        #必须 返回一个相关的对象
        print('--enter--')
        return 'disen'
    def __exit__(self,except_type,val,tb):
        #退出上下文时,被调用
        #except_type 如果存在异常,表示为异常类的实例对象
        #val 异常的消息Message
        #tb 异常的跟踪栈
        
        #返回True 表示存在异常,不向外抛出
        #返回False 表示存在异常,向外抛出
        print("--exit--")
        return True

1.3.2 with中使用
a =A()
with a as ret:
    print(ret)#ret是__enter__的返回值
    assert isinstance (ret,str)
    print('ok')
--enter--
disen
ok
--exit--

二、dao设计

DAO(Data Access Object)数据访问对象只是一种设计思想,目的是简化数据库成操作。针对实体类(数据,模型类)对象,封装一套与数据库操作的SDK(Software Develop Kit)。

合理的DAO的SDK 设计:

-dao(基础数据库操作模块)
|-- __init__py
|-- base.py
-entity(实体类模块)
|-- user
|-- order
-db (具体数据操作)
|-- user_db.py
|-- order_db.py
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值