爬虫

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\r\nhost: c1.com\r\n\r\nuser = alex & pwd = 123
# json,传请求体
# requests.post(
# ...,
# json={'user': 'alex', 'pwd': '123'}
# )
# GET / index http1.1\r\nhost: c1.com\r\nContent - Type: application / json\r\n\r\n{"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请求包括请求头, 请求体 头之间使用\r\n 隔开, 请求头与请求体之间使用\r\n\r\n隔开
# 响应同理


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

# json 发送
# json={1:"a",2,"b"} ---->\r\n\r\n{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)

posted @ 2019-10-12 14:02  下雨天,真好  阅读(196)  评论(0编辑  收藏  举报