zoukankan      html  css  js  c++  java
  • 爬虫

    1,初识爬虫

    import requests
    from bs4 import BeautifulSoup
    import os
    url="https://www.58pic.com/"
    response = requests.get(url)
    response.encoding='utf8'
    # print(response.text)
    soup = BeautifulSoup(response.text,"html.parser")

    # div = soup.find(name="div",attrs="id:xxxxx") # 返回值都是对象 obj.text返回标签中的值文本
    # div.find_all("li") # 查找里边的li标签
    # 唯一的时候用find,多个使用find_all
    # print(url.rsplit("/",maxsplit=1)) # rsplit 从后向前分割,maxsplit 指定分割次数
    ret = soup.find_all(name="img")
    for img in ret:
    src = img.get("src")
    if src:
    ret = requests.get("https:"+src)
    name = src.rsplit("/",maxsplit=1)[1]
    with open(os.path.join(os.path.join(os.getcwd(),"img"),name),"wb") as f:
    f.write(ret.content)
    # 通过继承实现java的接口功能
    """
    class A:
    def fun():
    raise NotImplementdError("子类没有实现父类方法")
    class B():
    pass
    obj=B()
    obj.fun()
    通过此方式实现调用方法报错,注意只有在(调用)的时候才会报错

    """

    # ==============================================
    """
    1,直接通过request.get()获取页面没有携带请求信息,容易别反爬发现
    2,因此需要携带数据,仿照浏览器
    requests.get(
    url="xxx",
    headers={
    "user-agent":"浏览器信息" 一般情况下这个即可,若还不可以,使用浏览器访问,逐个加上请求头即可
    }
    )

    登录爬虫
    1,请求头
    2,数据
    header中 data={"phone":"xxxx".......} 返回ret

    获取cookies
    ret.cookies.get_dict() cookies做为字典返回

    下次发送数据时带上
    headers中 cookies={xxx}或 ret.cookies.get_dict() 有的网站这样即可,但有的不行
    cookies 是放在请求头中的
    1,访问主页,生成cookies, 登录时提交cookie,使生效, 此时再次返回的数据还有cookie 但它是无用的cookies
    2,自动登录github
    a,get主页,找到input 获取csrf_token
    b,发送数据 csrf 用户名,密码,cookies
    c,访问url,携带cookies
    3,请求主页后,会在请求头加字段或html中加字段,登录时返回
    re.findall("xxx='(.*?)'",文本,re.S)[0] 获取第一个
    """
    # =================================
    # requests.get() 中没有data,不用传数据 post里边有
    # 若在里边中加入 params={"k1":"v1"} 此时请求头把它转为?参数及嵌入url get post都有

    # data,传请求体
    # requests.post(
    # ...,
    # data={'user': 'alex', 'pwd': '123'}
    # )

    # GET / index http1.1 host: c1.com user = alex & pwd = 123
    # json,传请求体
    # requests.post(
    # ...,
    # json={'user': 'alex', 'pwd': '123'}
    # )
    # GET / index http1.1 host: c1.com Content - Type: application / json {"user": "alex", "pwd": 123}

    # 代理 proxies
    # 无验证
    proxie_dict = {
    "https:/xxxx":"yyy", # 为单独url设置代理
    "http": "61.172.249.96:80",
    "https": "http://61.185.219.126:3128",
    }
    ret = requests.get("https://www.proxy360.cn/Proxy", proxies=proxie_dict)

    # 验证代理
    from requests.auth import HTTPProxyAuth

    proxyDict = {
    'http': '77.75.105.165',
    'https': '77.75.106.165'
    }
    auth = HTTPProxyAuth('用户名', '密码')

    r = requests.get("http://www.google.com",proxies = proxyDict, auth = auth)
    print(r.text)
    # 发送文件
    file_dict = {
    'f1': open('定制文件名','xxxx.log', 'rb')
    }
    requests.request(
    method='POST',
    url='http://127.0.0.1:8000/test/',
    files=file_dict
    )
    # =======================================================
    # 认证 auth
    # 内部:用户名和密码,用户和密码加密,放在请求头中传给后台。例如:路由器登录弹窗
    # - "用户:密码"
    # - base64("用户:密码")
    # - "Basic base64("用户 | 密码")"
    # - 请求头:Authorization: "basic base64("用户 | 密码")" 我们使用时,构造这个请求头即可

    from requests.auth import HTTPBasicAuth, HTTPDigestAuth # 通过该模块生成

    ret = requests.get('https://api.github.com/user', auth=HTTPBasicAuth('wupeiqi', 'sdfasdfasdf'))
    print(ret.text)
    # =======================================================
    # 超时时间 连接1s就返回
    # ret = requests.get('http://google.com/', timeout=1)
    # print(ret)
    # 连接5s,连接上1秒返回
    # ret = requests.get('http://google.com/', timeout=(5, 1))
    # print(ret)
    # =======================================================
    # 允许重定向 allow_redirects ,访问百度,百度让你转到搜狐,你去还是不去,若不去,没有响应体,只有响应头
    ret = requests.get('http://127.0.0.1:8000/test/', allow_redirects=False)
    print(ret.text)
    # =======================================================
    # 大文件下载 若通过普通方式,文件过大内存放不下
    # 设置stream为true表示一点一点下载,为false表示全部到内存
    from contextlib import closing
    with closing(requests.get('http://httpbin.org/get', stream=True)) as r1:
    # 在此处理响应。
    for i in r1.iter_content():
    print(i)
    # =======================================================
    # 证书(公钥)
    # 用户访问服务器的时候要携带公钥,公钥位于一个地方(服务方要使用,所以交钱),使用时自动下载了,系统帮你携带
    # 自定义证书, 用户访问时需要下载证书,访问时携带
    requests.get('http://127.0.0.1:8000/test/', cert="xxxx/xxx/xxx.pem") # 一个证书
    requests.get('http://127.0.0.1:8000/test/', cert=("xxxx/xxx/xxx.pem", "xxx.xxx.xx.key")) # 前边证书,后边秘钥
    requests.get('http://127.0.0.1:8000/test/', cert="xxxx/xxx/xxx.pem")
    # =======================================================
    session = requests.sessions()
    session.get("xxxx") # 第一次访问
    session.get("xxxx") # 第二次访问 可能第二次访问需要添加cookies,通过此方式不用每次手动添加
    # =======================================================
    # beautifulsoup https://www.cnbolg.com/wupeiqi/articles/6283017.html
    # ======================================================
    """
    轮询:实时刷新,定时器,获取实施效果
    长轮询:把请求保存30s,最大就是30s,请求回去后再次请求,再被保存30s, 以此达到实施效果
    $(function(){}) 通过此方式对于个更新的标签同样生效
    直接写function()对于新的ajax添加的组件可能时间失效
    绑定时间的时候使用委托式 on的方式

    长轮询实现方式:队列
    也可以使用webocket实现,但是兼容性不好
    from flask import Flask,render_template,request,jsonify,session
    import uuid
    import queue

    app = Flask(__name__)
    app.secret_key = 'asdfasdfasd'


    USERS = {
    '1':{'name':'贝贝','count':1},
    '2':{'name':'小东北','count':0},
    '3':{'name':'何伟明','count':0},
    }

    QUEQUE_DICT = {
    # 'asdfasdfasdfasdf':Queue()
    }

    @app.route('/user/list')
    def user_list():
    user_uuid = str(uuid.uuid4())
    QUEQUE_DICT[user_uuid] = queue.Queue()

    session['current_user_uuid'] = user_uuid
    return render_template('user_list.html',users=USERS)

    @app.route('/vote',methods=['POST'])
    def vote():
    uid = request.form.get('uid')
    USERS[uid]['count'] += 1
    for q in QUEQUE_DICT.values():
    q.put(USERS)
    return "投票成功"


    @app.route('/get/vote',methods=['GET'])
    def get_vote():
    user_uuid = session['current_user_uuid']
    q = QUEQUE_DICT[user_uuid]

    ret = {'status':True,'data':None}
    try:
    users = q.get(timeout=5)
    ret['data'] = users
    except queue.Empty:
    ret['status'] = False

    return jsonify(ret)

    if __name__ == '__main__':
    app.run(host='192.168.13.253',threaded=True)
    # app.run(threaded=True)
    """

    # http请求包括请求头, 请求体 头之间使用 隔开, 请求头与请求体之间使用 隔开
    # 响应同理


    # requests中 ContentType默认是:urlencode-form....
    # request.POST 获取数据时会检测是不是url..这个类型
    # data发送数据时
    # data={1:"a",2,"b"} ---> 1=a&2=b contentType 就是默认的类型 使用post可获得数据
    # data=json.dumps({1:"a",2,"b"}) ---> {1:"a",2,"b"}
    # data=b"abcd" -> 'abcd'

    # json 发送
    # json={1:"a",2,"b"} ----> {1:"a",2,"b"},
    # 请求头中会添加ContentType:application/json,data不会,
    # 不是ContentType默认类型,使用post无法获取
    # 使用request.body --> {1:"a",2,"b"}
    # 是字节,先转换为字符串,再反序列化-->字典

    # 出现FormDATA或表单数据 就是 &连接的第一种方式
    # requestpayload json格式 直接是
    # json={1="a",2="b"}
    # 或使用data =json.dumps({}) 这种方式,若有中文data =json.dumps(bytes({},encoding="utf8"),ensure_ascii=False)

  • 相关阅读:
    Spring 中的邮件任务
    Spring 定时任务
    java中同步交互 与 异步交互
    Springboot 版本包冲突
    Derby 配置环境变量
    Springboot中的Web服务Tomcat改为Jetty
    二叉树中和为某一值的路径
    0-Java中this和super的用法总结
    树9:二叉搜索树的后序遍历
    位运算-输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
  • 原文地址:https://www.cnblogs.com/Dean0731/p/11661193.html
Copyright © 2011-2022 走看看