14--爬虫回顾和重点经验

01.浏览器

# 一个网页的加载全过程
1. 服务器端渲染
    html的内容和数据在服务器进行融合.
    在浏览器端看到的页面源代码中. 有你需要的数据

2. 客户端(浏览器)渲染
    html的内容和数据进行融合是发生在你的浏览器上的.
    这个过程一般通过脚本来完成(javascript)

我们通过浏览器可以看到上述加载过程

# 数据在浏览器的位置:
network --->  All  或  Fetch/XHR  或 JS   # 99%只会在这三个里

02.requests

# requests模块
  是python的一个非常完善的一个第三方模块,专门用来模拟浏览器进行网络请求的发送
    
# 本质就是 模拟成浏览器的样子

    

# url:
    协议     域名  端口(80) 资源文件路径   参数
    http://www.baidu.com/s?name=alex&age=185
    https://www.baidu.com/s?name=alex&age=185
# 发送get请求
# 参数类型:query string parameteres

# 方式: params 和 url传参. 二选一即可
requests.get("https://www.baidu.com/s?ie=UTF-8&wd=周杰伦")


resp = requests.get("https://www.baidu.com/s",
params={
    "ie": "UTF-8",
    "wd": "周杰伦"
})  # params 是专门给get请求增加参数的
# 发送post请求

# 参数类型:formdata 或 urlcode
requests.post(url, data={"直接给字典就可以了"})


# 参数类型:request payload, 能直观的看到是json类型的数据
requests.post(url, json={"直接给字典就可以了"})

requests.post(url, data=json.dumps({直接给字典就可以了}), headers={
    "Content-Type": "application/json; charset=UTF-8"
})



### get/pos对比
get/post, 是http的请求方式   # 我们只需要根据抓包里面的状况去选择使用
get和post的传参方式是不一样的 
get的参数,最终都会被添加到url身上 ###
# 状态码 (HTTP协议的状态码)
200 系列 一般指的是你当前本次和服务器进行通信没有问题

300 系列 一般指的是重定向. 注意在响应头上能看到location字样
        写爬虫的时候. 基本上不用管302 因为requests可以自动帮你完成这个重定向的动作

403 系列 一般都是被风控拦截了  

404 系列 资源文件路径走丢了 
       你的url不存在.再服务器上人家没办法给你想要的内容


500 系列 服务器内部出现了错误
    若浏览器有错,那就是本身服务有问题
    
    若浏览器上啥事儿没有. 你的程序一跑,就500. 基本上就是你给的参数有问题. 让服务器无法正常工作 

# 解决:重试 + 异常捕获
for i in range(10):
    try:
        发请求
        break
    except Exception as e:
        print("出错了")

03.简单反爬(header)

请求头

# 请求头参数

User-Agent  # 用户用什么设备发送的请求, 直接复制粘贴就好

Cookie      # 服务器 记录在浏览器上 的一个字符串, 写入浏览器上的一个文件中
  
    # 作用: 和服务器之间保持住会话.  session:同理,记录在服务器端的
    
    # 解决:
        1.可以直接从浏览器抓包中复制. (某些网站可以)

        2.requests.session()来保持会话
        
        注意:requests.session(). 可以帮你处理set-cookie的内容.
             它不能帮你处理javascript处理的cookie的内容.
             如果网站是用js来维护cookie的, name你需要自己来写代码处理这坨逻辑

Referer   # 用来检测上一个url是什么. 一般直接复制粘贴即可   eg: 图片防盗链


网页自己添加的一些参数   # 最蛋疼的  JS逆向的地方



### session的使用
session = requests.session()

session.headers = {

}

session.cookie = {

}

session.get()
session.post()

响应头

# 响应头参数
Location    # 302重定向地址    我们不管

Set-Cookie  # session自动维护 我们也不管

网页自己添加的一些参数  # 一般情况下是不用管的. 万中无一的那种网站会使用到

04.数据解析

# html
    re     # 常见使用场景:在html中获取到js的一部分代码(字符串)
    
    xpath  # 常见使用场景:解析常规的html结构
        from  lxml import etree
        tree = etree.HTML(response.text)
        res = tree.xpath("xxxxx/xxx/xxx")
        
        # etree的xpath,默认返回的是列表. 要判断空的情况
        if res:
            res[0]
        else:
            xxx
        
    bs4  # 常见使用场景:解析 xml类型和 svg(使用XML格式,定义图像)
        .find()
        .findall()

        
# json
    response.json()
    
    json.loads(response.text)

    # 注意:
    如果遇到反爬. 很可能拿到的东西 和 抓包工具获取的 不一致
    切记, 先打印response.text. 确定好 返回的内容是json格式. 才开始转化

    
# jsonp    一般是 network 中 JS 请求类型 返回的数据类型

    # 这个"jsonpxxxxxx",也在该url的 请求参数中看得到
        callback: jsonpxxxxxx
    
    # eg:
    jsonpxxxxxx({json})  => {json}
    
    # 解决:想办法去掉左右两端的xxxxxx( ) => 得到的就是json
    "jsonpxxxxxx({json})".replace("xxxxxx(", "")[:-1]

05.多任务异步爬虫

# 一般情况下:
最多是 多进程 + 多线程 就够了, 协程不仅麻烦,而且基本正规的网站 都有频率等限制,用不到协程这么高性能


# 进程是资源单位. 进程与进程之间是隔离的
p1 = Process()
p2 = Process()

Queue / redis   # 进程通信:队列 和 redis


# 线程是执行单位,多个线程共享 同一个进程的资源


# 协程是人为干预,主进程下 主线程的任务执行情况,将耗时任务 挂起,并切换到其他任务 (最麻烦的)

06.数据存储

# MySQL、Mongodb、Redis、CSV


### 1 mysql
# 用Navicat创建表格即可
增加数据
    insert into 表(字段1, 字段2, 字段3.....) values (值1, 值2, 值3.....)
修改数据
    update 表 set 字段=值, 字段=值  where条件
删除数据
    delete from 表 where 条件
查询数据
    select * from 表 where 条件

# python如何操纵数据库
pymysql  
  # 注意:
    1.以字典形式返回数据    
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    
    2.避免sql注入问题   %s占位  模块自动拼接
    sql = "insert into class(cname, cmoney, cbanzhuren) values (%s, %s, %s)"
    cursor.execute(sql, (name, money, banzhuren))

    
    
### 2 redis
# redis存储数据的规则:
key -> 数据(单一字符串, 列表, 字典, 集合、有序集合)

    
    
    
### 3 存csv    客户一般用于 pandas进行数据分析
本质就是个文本文件,特点是:文件内的数据 默认 以'逗号,' 分隔,呈现一个表格形式
可以直接用excel打开,逗号会自动分隔到不同的单元格中


# 若数据文本本身包含 逗号,解决
# 解决1:将整个文本 用引号包裹,eg:'"樵,夫"'

f = open("data.csv", mode="w", encoding="utf-8")
f.write('樵,夫')
f.write(",")
f.write("18")
f.write(",")
f.write("5000")
f.write("\n")

# pandas 读取
import pandas

r = pandas.read_csv('data.csv', header=None)
print(r)


# 解决2:可自定义分割符,eg: '|'    通常不修改分割符
f = open("data.csv", mode="w", encoding="utf-8")
f.write('樵,夫')
f.write("|")
f.write("18")
f.write("|")
f.write("5000")
f.write("\n")


# pandas 读取
import pandas

r = pandas.read_csv("data.csv", sep="|", header=None)
r.to_excel("data.xls", header=False, index=False)  # 另存为xls格式

07.面向对象(基础)

# 核心是编程思想的转变

# 目前. 我们写的代码是什么思想. 面向过程
1.获取页面源代码
2.去解析页面源代码
3.去存储数据


# 面向对象: 你要操纵对象. 让对象给你干活
结局都是能喝到可乐.

让对象去操作   # 需要自己去创造对象
1.你得有对象   
2.你的对象得会去干活


# 怎么去造对象?
在编程的世界里. 想要造对象,需要先写类(泥人, 图纸, 你想想的那个样子)

# 1.先写类
class 类名:
    
def __init__(self, xxxx):
    self.xxxx = xxxx
    
def 方法名(self):
    pass


# 2.造对象
对象 = 类名(参数)
对象.方法名()

self:  当前正在执行这个功能的对象
posted @ 2024-04-11 16:54  Edmond辉仔  阅读(7)  评论(0编辑  收藏  举报