基础笔记

基础笔记

#!user/bin/env pyhon3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/11/22 14:09

#range()的三种创建方式
#随机数

第一种
r=range(10)
print(r)
print(list(r))

#第二种
rr=range(1,10)
print(list(rr))

# 第三种
rrr=range(1,10,2)
print(list(rrr))

#in
p=(8 in r)
print(p)

# not in
p=(8 not in r)
print(p)

#p=list[1,6,8,9,7,5,6,9,8,7,6]
sum=0
a=1
while a<=100:
    if a % 2 == 0:
        sum += a
    a+= 1
print(sum)

for  in

for item in 'Python':
    print(item)

for i in range(10):
     print(i)

for _ in range(5):
    print("人生苦短,我用python")

sum=0
for i in range(101):
    if i%2==0:
        sum+=i

print(sum)

#水仙花树
for item in range(100,1000):
    ge=item%10
    shi=item//10%10
    bai=item//100
    # print(ge,shi,bai)
    #判断
    if ge**3+shi**3+bai**3==item:
        print(item)

# 三行四列的矩形

for i in range(1,4):#行
    for j in range(1,5):#列
        print('*',end='\t')
    print()

# 九九乘法表
for i in range(1,10):
    for j in range(1,i+1):
        print(i,'*',j,'=',i*j,end='')
    print()

#流程控制语句break与continue在二重循环中的是使用

for i in range(5):
    for j in range(1,11):
        if j%2==0:
            # break
            continue
        print(j,end='\t')
    print()

# 列表

lst=['hello','Python',100]
print(lst[0],end='\t')

lst2=list(['hello','Python',100])
print(lst2[-2])

List

#!user/bin/env python3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/11/24 22:12

lst=['hello','world',100,'hello']
#
print(lst.index(100))
# #范围内获取相同元素
print(lst.index('hello',1,4))

lst=['hello','world',100,'hello',9,6,8,7]

for i in lst.index():
    print(i)

# 切片
# lst[start,stop,step]
lst=[10,20,100,30,9,6,8,7]
print(lst[1:5:1])#从1开始,到5结束,步长为1(默认)
print(lst[1:5:2])#步长为2
print(lst[:5:2])
print(lst[1::2])
print(lst[::2])

#步长是负数的时候

print("原列表",lst)
print(lst[::-1])
print(lst[7::-1])
print(lst[6:0:-2])

lst=[10,20,'Python','hello']
# 判断是否存在
print(10 in lst)
print(20 not in lst)
#遍历数组
for item in lst:
    print(item)

# 添加元素

# 从尾部
lst=[10,20,30,'python']
lst2=[50,"pppp"]
lst.append(100)
print(lst)

# #末尾一次性添加多个元素
lst.extend(lst2)
print(lst)

#在指定位置添加元素
lst.insert(1,90)
print(lst)

#在任意位置上添加N多个元素
lst3=[True,'hello','yho']
lst[1:]=lst3
print(lst)

# 删除指定元素
lst=[10,20,30,40,6,66,48,99,20,5]
lst.remove(30)
print(lst)

# 根据索引删除元素
lst.pop(1)
print(lst)

# 不指定索引,那么久直接删除最后一个元素
lst.pop()
print(lst)

# 切片操作
new_list=lst[1:5] #1-4的元素
print("原列表",lst)
print("切片后的:",new_list)

# 不产生新的列表对象,而是删除原列表的内容
lst[1:5]=[]
print(lst)

# 清除列表中的所有元素

lst.clear()
print(lst)

# 将列表对象删除
del lst
print(lst)

lst=[10,20,30,40]

# 根据索引修改一个值
lst[2]=100
print(lst)

# 切片修改内容

lst[1:3]=[300,400,500] #去掉两位,添加新值
print(lst)

# # 列表元素的排序操作
lst=[20,40,30,50,10,70]
# 升序
lst.sort()
print(lst)

# 通过指定参数(reverse=True),实现降序
lst.sort(reverse=True)
print(lst)

# 使用内置函数,实现升序排序
lst=[20,40,30,50,10,70]
# 升序排序
new_lsit=sorted(lst)
print(new_lsit)

# 使用内置函数,实现降序排序
desc_list=sorted(lst,reverse=True)
print(desc_list)

# 灵活使用
lst=[i*i for i in range(1,10)]
print(lst)
# 输出[1, 4, 9, 16, 25, 36, 49, 64, 81]

String

#!user/bin/env python3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/11/29 22:52

# 字符串的驻留机制
a='Python'
b="Python"
c='''Python'''
print(a,id(a))
print(b,id(b))
print(c,id(c))

# 字符串的查询操作
s='hello,hello'

# # 查找第一次出现的位置
print(s.index('lo'))
print(s.find('lo'))
#
# # 查询最后一次出现的位置
print(s.rindex('lo'))
print(s.rfind('lo'))

# 对比查询不存在的内容
print(s.index('p'))#会抛异常

# find是常用的查询字符串的方法,可以返回一个值提供判断
print(s.find('p'))#给个 -1
print(s.rfind('p'))#给个 -1

print(s.rindex('p'))#会抛异常

# 字符串大小写转换操作的方法
# upper()         把字符串中所有字符都转成大写字母
# lower()         把字符串中所有字符都转成小写字母
# swapcase()      把字符串中所有大写字母转成小写字母,把所有小写字母都转成大写字母
# capitalize()    把第一个字符转换为大写,把其余字符转换为小写
# title()         把每个单词的第一个字符转换为大写,把每个单词的剩余字符转换为小写

#
s='hello,Python'
# # 都转换成大写
a=s.upper()
print(a)
#
# # 都转换成小写
print(s.lower())
#
# # 大小写互转
print(s.swapcase())
#
# # 每个英文单词的首字符都变成大写
print(s.title())

# 字符串内容对其操作的方法

#
# center()    居中对齐,第1个参数指定宽度,第2个参数指定填充符,第2个参数是可选的,默认是空格,如果设置宽度小于实际宽度则则返回原字符串左对齐,
#             第1个参数指定宽度,第2个参数指定填充符,第2个参数是可选的,默认是空格如
#
#
# ljust()     果设置宽度小于实际宽度则则返回原字符串字符串对齐右对齐,第1个参数指定宽度,第2个参数指定填充符,第2个参数是可选的,默认是空格如
#
# rjust()     果设置宽度小于实际宽度则则返回原字符串右对齐,左边用0填充,该方法只接收一个参数,用于指定字符串的宽度,如果指定的宽度
#
#
#zfill()     #小于等于字符串的长度,返回字符串本身
#
#
#

s='hello Python'

# # 居中对齐
print(s.center(20,'*'))
# # 左对齐
print(s.ljust(20,'*'))
print(s.ljust(10))
print(s.ljust(20))
#
# # 右对齐
print(s.rjust(20,'*'))
print(s.rjust(20))
print(s.rjust(10))

# 右对齐,使用0填充
print(s.zfill(20))
print(s.zfill(10))
print('-4564'.zfill(8))

String Application

#!user/bin/env python3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/12/3 20:14

# 字符串分割

s='hello world Python'
# 没有指定分割符 通过空格实现分割
lst=s.split()
print(lst)

# 指定分割符
s1='hello|world|Python'
print(s1.split(sep='|'))

# 指定分割一个
print(s1.split(sep='|',maxsplit=1))

# rsplit()从右侧开始分割
print(s.split())
# 指定分割符
print(s1.rsplit(sep="|"))
# 指定分割一个
print(s1.rsplit(sep="|",maxsplit=1))

# 判断字符串操作的方法

# isidentifier()  判断指定的字符串是不是合法的标识符
# isspace()       判断指定的字符串是否全部由空白字符组成(回车、换行,水平制表符)
# isalpha()       判断指定的字符串是否全部由字母组成
# isdecimal(      判断指定字符串是否全部由十进制的数字组成
# isnumeric()     判断指定的字符串是否全部由数字组成
# isalnum()       列断指定字符串是否全部由字母和数字组成

s='hello,Python'
print('1',s.isidentifier())
print('2','hello'.isidentifier())
print('3','张三_'.isidentifier())
print('4','张三_123'.isidentifier())

# isspace()       判断指定的字符串是否全部由空白字符组成(回车、换行,水平制表符)
print('5','\t'.isspace())
# isalpha()       判断指定的字符串是否全部由字母组成
print('6','abc'.isalpha())
print('7','张三'.isalpha())
print('8','张三1'.isalpha())

# isdecimal(      判断指定字符串是否全部由十进制的数字组成
print('9','123'.isdecimal())
print('10','123四'.isdecimal())

# isnumeric()     判断指定的字符串是否全部由数字组成
print('11','123'.isnumeric())
print('12','123四'.isnumeric())
print('13','张三123'.isnumeric())

# isalnum()       列断指定字符串是否全部由字母和数字组成
print('14','我的ll'.isalnum())
print('15','abc1'.isalnum())
print('16','abc!'.isalnum())

# 字符串替换  replace()  第1个参数指定被替换的子串,
# 第2个参数指定替换子串的字符串,该方法返回替换后得到的字符串,
# 替换前的字符串不发生变化,调用该方法时可以通过第3个参数指定最大替换次数
#
# 字符串的合并  join()  将列表或元组中的字符串合并成一个字符串

s='hello,Python'
# 替换字符
print(s.replace('Python','Java'))

s1='hello,Python,Python,Python'
# 只替换相同对的两个字符
print(s1.replace('Python','Java',2))

lst=['hello','Java','Python']
# 合并列表
print('|'.join(lst))
# 合并列表
print(' '.join(lst))
# 合并元祖
t=('hello','Java','Python')
print(' '.join(t))

print('*'.join('Python'))

String Compare

#!user/bin/env python3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/12/3 20:59

# 进度条显示
import time
from tqdm import tqdm
for i in tqdm(range(1000)):
    time.sleep(.01)

Set

#!user/bin/env python3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/11/27 16:08

# 什么是集合
# ·集合
# · Python语言提供的内置数据结构
# ·与列表、字典一样都属于可变类型的序列
# ·集合是没有value的字典

# 创建
# 第一种使用{}
s={2,3,4,5,6,7,7}#集合中的元素不能重复
# print(s)

# 第二种使用set
s1=set(range(6))
print(s1,type(s1))

s2=set([1,2,3,4,5,6,6])
print(s2,type(s2))

s3=set((1,2,3,4,4,5,6,65))
print(s3,type(s3))

s4=set('Python')
#集合中的元素是无序的
print(s4,type(s4))

#空集合
s5=set()
print()

Set Application

#!user/bin/env python3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/11/27 16:37

# 集合的相关操作
# ·集合元素的判断操作
#     in或not in
# ·集合元素的新增操作
#     ·调用add()方法,一次添中一个元素
#     ·调用update()方法至少添中一个元素
# ·集合元素的删除操作
#     ·调用remove()方法,一次删除一个指定元素,如果指定的元素不存在抛出KeyError
#     ·调用discard()方法,一次删除一个指定元素,如果指定的元素不存在不抛异常
#     ·调用pop()方法,一次只删除一个任意元素
#     ·调用clear()方法,清空集合

s={10,20,30,40,50,666,444}
# 判断
# print(10 in s)
# print(100 in s)

# 新增  一次添加一个元素
s.add(80)
print(s)

# 新增  一次添加至少一个元素
s.update({200,300,400})
print(s)

s.update([500,999])
s.update((95,74))
print(s)

# 删除   如果没有对应值会报错
s.remove(500)
print(s)

#删除   如果没有对应值不会报错
s.discard(100)
print(s)

#删除   任意删除一个元素   不能指定参数
s.pop()
s.pop()
print(s)

#清空   clear

s.clear()
print(s)

Set Relation

#!user/bin/env python3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/11/27 22:53

# 集合间的关系
# ·两个集合是否相等
#     ·可以使用运算符==或!=进行判断
# ·一个集合是否是另一个集合的子集
#     ·可以调用方法issubset进行判断
#     ·B是A的子集
# —个集合是否是另一个集合的超集
#     ·可以调用方法issuperset进行判断
#     ·A是B的超集
# ·两个集合是否没有交集
#     ·可以调用方法isdisjoint进行判断

s={10,20,30,40}
s2={30,40,20,10}
# # 两个集合是否相等   集合是无序的
print(s==s2)
print(s!=s2)

# 一个集合是否是另一个集合的子集
s1={10,20,30,40,50,60}
s2={10,20,30,40}
s3={10,20,90}
print(s2.issubset(s1))
print(s3.issubset(s1))

# 一个集合是否是另一个集合的超集

print(s1.issubset(s2))
print(s1.issubset(s3))

# 两个集合是否含有交集
print(s2.isdisjoint(s3))
# 两个集合是否含有交集
s4={100,200,300}
print(s2.isdisjoint(s4))

# 交集
s1={10,20,30,40,50,60}
s2={10,20,30,40,70}
print(s1.intersection(s2))
print(s1 & s2) #intersection和&同等操作

# 并集操作
print(s1.union(s2))
print(s1 | s2)  #union和| 是同等操作的

# 差集操作
print(s1.difference(s2))#s1-s2的结果
print(s1-s2)

# 对称差集
print(s1.symmetric_difference(s2))
print(s1 ^ s2)

# 列表生成式公式
lst=[i*i for i in range(10)]
print(lst)

# 集合生成式
sets={i*i for i in range(10)}
print(sets)

Time

#!user/bin/env python3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/12/2 15:57

# 格式   含义
# %Y   完整的年份
# %m   月份(01 - 12)
# %d   一个月中的第几天(01 - 31
# %H   一天中的第几个小时(24小时制,00 - 23)
# %M   分钟数(00 - 59)
# %S   秒(01 - 61)

import time

# 时间戳
# 从1970年1月1日00:00:00标准时区诞生到现在时间一共过了多少秒。
timestamp=time.time()
print(timestamp,type(timestamp))

# 有时候可能我们可能需要模仿一些IO请求,假装让程序休眠一下,所以需要用到time的sleep函数。
# 睡眠1秒
time.sleep(1)

# 本地时区需要用到time的localtime方法。
t=time.localtime()
print(t,type(t))

# localtime还能接收一个时间戳参数。
# 将时间戳转换成 struct_time 对象
t = time.localtime(1606395685.1878598)  # type:time.struct_time
print(t, type(t))

# 简单的时间格式
t=time.ctime()
print(t,type(t))

# 同理,time.ctime()也是可以接收一个时间戳的。
t = time.ctime(1606395685.1878598)  # type:str
print(t, type(t))

# # 日期格式 -> 字符串(strftime)
t=time.localtime()
t_str=time.strftime("%Y-%m-%d",t)
print(t_str,type(t_str))

# # 字符串日期 -> 日期(strptime)
t_str = "2020-11-02"
t_time = time.strptime(t_str, "%Y-%m-%d")  # type:time.struct_time
print(t_time, type(t_time))

# 注:datetime和time是两个不同的类型,不能混用。!!!!!
from datetime import datetime

t = datetime.today()  # type:datetime
print(t, type(t))
print(t.year)  # 年份
print(t.month)  # 月份

# 返回本地时间datetime.now()
t = datetime.now()  # type:datetime
print(t,type(t))

# 返回标准时间datetime.utcnow()
t = datetime.now()
print("东八区时间:", t)
t = datetime.utcnow()  # type:datetime
print("UTC时间:", t)

# 时间戳转datetime
# 有时候,我们拿到的,就是时间戳,那就只能转了。
# 时间戳
timestamp = time.time()
# print(timestamp)
print(f"timestamp:{timestamp},type:{type(timestamp)}")
# 时间戳转datetime
t = datetime.fromtimestamp(timestamp)
print(f"t:{t},type:{type(t)}")
# print(t)

datetime -> 字符串日期(strftime)
t = datetime.now()
str_datetime = t.strftime("%Y-%m-%d %H:%M:%S")
print(f"字符串日期:{str_datetime},type:{type(str_datetime)}")

# 字符串日期 -> datetime(strptime)
str_datetime = "2020-11-29 22:05:20"
t = datetime.strptime(str_datetime, "%Y-%m-%d %H:%M:%S")
print(f"t:{t},type:{type(t)}")

# 时间加减
#
# 这才是本次的重头戏,好像只有datetime这个包,才有时间加减的。
#
# 时间加减的具体用途很多,必须多久过期什么的,多久之后提醒,都需要提前计算时间,还是很重要的。

from datetime import datetime
import datetime as idatetime

# 可以发现,这个时间确实是+成功了。
#
# 但是自带的时间加减,有个题,只能加天,不能加月,甚至年。
#
# 如果想要时间+月等,还要自己写逻辑。

t = datetime.now()
print(f"当前时间:{t}")
three_day = t + idatetime.timedelta(days=3)
print(f"三天后时间:{three_day}")

from datetime import datetime
from dateutil.relativedelta import relativedelta

# datetime时间自由加减

t = datetime.now()
print(f"当前时间:{t}")
three_time = t + relativedelta(months=3)
print(f"三个月后时间:{three_time}")
one_year = t+relativedelta(years=1)
print(f"一年后时间:{one_year}")
up_year = t+relativedelta(years=-1)
print(f"去年这个时间:{up_year}")

# 总结
#
# 本篇主要讲述的是关于Python时间的相关总结,相对来说,更推荐使用datetime。
#
# 需要注意的是,time和datetime是俩类型,是不能混用的。
#
# 其实最重要的是字符串时间->时间类型,这个在实际中用的非常多!
#
# 顺便还有python-dateutil的relativedelta相关方法,能够自由加减时间,算是挺方便的。

yuanzu

#!user/bin/env python3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/11/27 15:17

# ·元组
# Python内置的数据结构之一,是一个不可变序列
# ·不可变序列与可变序列
# ·不变可变序:字符串、元组
# ·不变可变序列:没有增、删,改的操作·可变序列:列表、字典
# ·可变序列:“可以对序列执行增、删、改操作,对象地址不发生更改

#不可变序列
s='hello'
print(id(s))
s=s+'world'
print(id(s))
print(s)

# 可变序列(他们的id一样的)
lst=[10,20,30]
print(id(lst))
lst.append(300)
print(id(lst))

#正题,元祖的创建方式
#第一种 使用()
t=('Python','world',98)
print(t)
print(type(t))

#第二种创建方式 使用内置函数tuple()
t1=tuple(('Python','world',98))
print(t1)
print(type(t1))

# 空列表
lst=[]
lst1=list()
# 空字典
d={}
d2=dict()
# 空元祖
t4=()
t5=tuple()

print('空列表',lst,lst1)
print('空字典',d,d2)
print('空元祖',t4,t5)

t=(10,[20,30],40)
print(t)
print(t[0],type(t[0]))
print(t[1],type(t[1]))
print(t[2],type(t[2]))
#向元祖里面的列表里面添加元素
t[1].append(100)
print(t)

# 元祖的遍历
t=('Python','world',98)

# 第一种,使用索引
print(t[0])

# 第二种for in
for item in t:
    print(item,end='\t')

操作Excal表


# 创建一个新的excal表格,并写入内容
# 
import xlsxwriter

#创建一个新的xlsx文件(如果原有同名文件会被覆盖)
workbook = xlsxwriter.Workbook("Expenses01.xlsx")

#创建一个新的表单,默认名称为 “sheet1”,输入字符参数可指定名称
worksheet = workbook.add_worksheet()

expenses = (
    ['Rent', 1000],
    ['Gas' ,  100],
    ['Food',  300],
    ['Gym' ,   50],
)

#worksheet 默认是从0行、0列开始计数
row = 0
col = 0

#worksheet.write 方法将数据写入 xlsx 表格中
#参数依次为:行号、列号、数据、[格式]
for item, cost in (expenses):
    worksheet.write(row, col ,    item)
    worksheet.write(row, col + 1, cost)
    row += 1

#显式关闭workbook,若不显式指定,则作用域结束后自动关闭
workbook.close()

------------------------------------------------------------

#####读取内容后,追加到excal表里

from xlrd import open_workbook
from xlutils.copy import copy
import requests
import json

# api
url = 'https://www.zhihu.com/api/v4/members/wisphilo?include=allow_message%2Cis_followed%2Cis_following%2Cis_org%2Cis_blocking%2Cemployments%2Canswer_count%2Cfollower_count%2Carticles_count%2Cgender%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics'

# header的目的是模拟请求,因为该api设置了反爬取
header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
}

doc = requests.get(url, headers=header)  # 发起请求
doc.encoding = 'utf-8'  # 设置编码为utf-8

data = json.loads(doc.text)  # 将json字符串转为json<br><br>#根据位置查找数据
print('用户名:', data.get('name'))
# print('个人描述:', data.get('headline'))
# print('职务:' + data.get('employments')[0].get('job').get('name'))
# print('回答:', data.get('answer_count'))
# print('文章:', data.get('articles_count'))
# print('关注者:', data.get('follower_count'))
name=data.get('name')

r_xls=open_workbook("Expenses01.xlsx")#读取excal文件
row=r_xls.sheets()[0].nrows#获取已有行数
excal = copy(r_xls)#将xlrd的对象转化为xlwt的对象
table= excal.get_sheet(0)#获取要操作的sheet
#对excal表追加一行内容
table.write(row,0,'名字')
table.write(row,1,name)
excal.save("Expenses01.xlsx")

--------------------------------------------------------

!/usr/bin/env python
-*- coding:utf-8 -*-

from xlrd import open_workbook
from xlutils.copy import copy

r_xls = open_workbook("test.xls") # 读取excel文件
row = r_xls.sheets()[0].nrows # 获取已有的行数
excel = copy(r_xls) # 将xlrd的对象转化为xlwt的对象
table = excel.get_sheet(0) # 获取要操作的sheet

#对excel表追加一行内容
table.write(row, 0, '内容1') #括号内分别为行数、列数、内容
table.write(row, 1, '内容2')
table.write(row, 2, '内容3')

excel.save("test.xls") # 保存并覆盖文件

os库对文件的操作

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# print("hello python")
#
#创建并写入文本
# fp=open('text.txt','a+')
# print('hello python',file=fp)
# fp.close()

#读取文件内容
# 第一种
# fp=open("text.txt",'r+',encoding="utf-8")
# data=fp.read()
# print(data,type(data))
# fp.close()

# 第二种
# fp=open('text.txt','r+')
# str=fp.read(5)#输出五个字符
# print("里面的内容为:",str)
# fp.close()

# 文件定位
# 打开一个文件
# fp=open('text.txt','r+')
# str=fp.read(5)#输出五个字符
# print("里面的内容为:",str)
# # 查找当前位置
# position=fp.tell()
# print("当前的位置是:",position)
# # 把指针再次重新定位到文件开头
# position=fp.seek(0,0)
# str=fp.read(5)
# print("重新读取字符串:",str)
# # 关闭打开的文件
# fp.close()

-----------------------------------------------------------------------
#os库的基本使用
# 重命名和删除文件
# rename()方法:
# rename()方法需要两个参数,当前的文件名和新文件名。
# os.rename(current_file_name, new_file_name)

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import os
#重命名文件text.txt到test.txt
os.rename("text.txt","test.txt")

# 删除一个已经存在的文件test2.txt
os.remove("test.txt")

# 在当前目录下创建一个新目录test。
os.mkdir("newdir")

# 用chdir()方法来改变当前的目录
os.chdir("newdir")

# 进入newdir目录
# 将当前目录改为"/home/newdir"
os.chdir("/home/newdir")

# getcwd()方法显示当前的工作目录。
print(os.getcwd())

# rmdir()方法删除目录,目录名称以参数传递。
os.remove("newdir")

Dictionary

#!user/bin/env python3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/11/25 22:47

# ·字典的特点
# ·字典中的所有元素都是一个key-value对, key不允许重复,value可以重复
# ·字典中的元素是无序的
# ·字典中的key必须是不可变对象
# ·字典也可以根据需要动态地伸缩
# ·字典会浪费较大的内存,是一种使用空间换时间的数据结构

# {'key':value}
# 使用{}创建和应用
# 第一种创建方法
scores={'张三':100,'李四':98,'王五':45}
print(scores)

# 第二种创建方法dict函数自动识别
student=dict(name='jack',age=20)
print(student)

# 空字典
d={}
print(d)

# 字典中的元素获取
scores={'张三':100,'李四':98,'王五':45}
# # 第一种,使用[]
print(scores['张三'])

# 第二种get()方法
print(scores.get('张三'))
print(scores.get('玛琪'))#None
print(scores.get('玛琪',99))# 当键不存在时,99是给的默认值

# key的判断
scores={'张三':100,'李四':98,'王五':45}
print('张三' in scores)

del scores['张三']#删除指定的key-value对
scores.clear()
print(scores)

# 添加内容
scores['陈刘']=98
print(scores)

# 修改元素
scores['陈刘']=100
print(scores)

scores={'张三':100,'李四':98,'王五':45}

# 获取所以的key

# 将所有的key组成的视图转成列表
print(list(keys))

# 获取所有的value
values=scores.values()
print(values)
print(type(values))
#将所有的values组成的视图转成列表
print(list(values))

# 获取所有键值对

items=scores.items()
print(items)
#dict_items([('张三', 100), ('李四', 98), ('王五', 45)])
print(type(items))

# #转换之后的列表元素是由元祖组成[('张三', 100), ('李四', 98), ('王五', 45)]
print(list(items))

#字典元素的遍历
for item in scores:
    print(item,scores[item],scores.get(item))

Dictionary Application

#!user/bin/env python3
# -*- coding:utf-8 -*-
# Email 23198899766@QQ.com
# Time : 2020/11/27 14:39

# 获取value         字典名[key]
# 删除key-value对    字典名.get(key)
# 修改/新增           del字典名[key]
# in /not in          字典名[key]=value

#字典生成式
items=['English','Chinese','Math']
prices=[98,95,100]

#upper()是大写的意思
d= {item.upper():price   for item,price in zip(items,prices)}
print(d)

#这种方法可以将zip拆成两部分
print(list(d),list(d.values()))

操作Mysql

import MySQLdb

#查询数量
def Count(cur):
   count=cur.execute('select * from Student')
   print ('there has %s rows record' % count)

#插入
def Insert(cur):
   sql = "insert into Student(ID,Name,Age,Sex)values(%s,%s,%s,%s)"
   param = (2,'xiaoming',24,'boy')
   cur.execute(sql,param)

#查询 
def  Select(cur):  
   n = cur.execute("select * from Student")    
   print ("------")
   for row in cur.fetchall():    
      for r in row:    
         print (r)
      print ("------" )   
#更新
def Update(cur):
   sql = "update Student set Name = %s where ID = 2"   
   param = ("xiaoxue")    
   count = cur.execute(sql,param)

#删除
def Delete(cur):    
   sql = "delete from Student where Name = %s"   
   param =("xiaoxue")    
   n = cur.execute(sql,param)   

try:
   conn=MySQLdb.connect(host='localhost',user='root',passwd='123456',db='python',port=3306)
   cur=conn.cursor()
   #数量
   Count(cur)
   #查询
   Select(cur)
   #插入
   Insert(cur)
   print "插入之后"
   #查询
   Select(cur)
   #更新
   Update(cur)
   print "更新之后"
   #查询
   Select(cur)
   #删除
   Delete(cur)
   print "删除之后"
   #查询
   Select(cur)

   cur.close()
   conn.close()

except MySQLdb.Error,e:
   print "Mysql Error %d: %s" % (e.args[0], e.args[1])

selenium

特殊操作

send_keys后自动回车

这个就是不用找到点击按钮在点击

导包:from selenium.webdriver.common.keys import Keys

find...找到输入框.send_keys("内容", Keys.ENTER)

窗口的切换

1.切换到后面的窗口

当前面的点击一个会重新打开的一个click()后,开始切换窗口到跳转后的视角:driver.switch_to.window(web.window_handles[-1])#这个就是切换到当前的最后一个窗口,下标可以改

2.关闭一个,重定位

关闭当前定位的窗口

driver.close()

重定位到另一个窗口

driver.switch_to.window(web.window_handles[0])

处理iframe

切换进iframe

1.首先定位到iframe,复制iframe的xpath,使用selenium.find...xpath找到

2.注意!!!一个页面里面可能会有多个iframe,所以定位的时候,适用下标提前选择是哪个

3.使用driver.switch_to.frame(第一步定位的变量)

回到默认视角

也就是跳出iframe

driver.swicth_to.default_content()

scrapy常用命令

实例:

qsbk 普通类的scrapy + 翻页
wxapp crawl 类的scrapy
renren_login post请求 模拟登陆
douban_login post请求 模拟登陆
hyk 图片深度下载 + 翻页
boss crawl 类
useragent_demo 随机请求头和 IP

scrapy 安装

1、pip install scrapy

2、在windows 下,还需要安装pypiwin32 pip install pypiwin32
3、在ubuntu下,还需安装第三方库: sudo apt-get install python-devpython-pip libxml2-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev

scrapy框架详细步骤

一、创建爬虫项目Spider

1、选择合适的文件夹,在pycharm中的Terminal中输入: scrapy startproject XXX
2、cd Spider
3、创建爬虫文件
scrapy genspider -t crawl xxx_spider URL
4、新建 启动爬虫 文件
在根目录下新建 start.py
from scrapy import cmdline
cmdline.execute("scrapy crawl 爬虫名称".split())

二、修改爬虫文件

1、修改配置文件 setting
#(1)修改协议,请求头,下载路径
ROBOTSTXT_OBEY = False
from fake_useragent import UserAgent
DEFAULT_REQUEST_HEADERS = {
    'Accept': 'text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
    'User-Agent':str(UserAgent(verify_ssl=False).random),
    #'Referer': 'xxxxxx'  ,  #下载图片/文件需要
    #'Cookie': 'xxxxxx'  ,  #在settings里设置默认cookie(从浏览器复制一下,或者bp抓包),COOKIES_ENABLED=False 必须为False
    }
DOWNLOAD_DELAY = 0.5              # 设置延时下载
AUTOTHROTTLE_ENABLED = True      #默认False;为True表示 启用AUTOTHROTTLE扩展
AUTOTHROTTLE_START_DELAY = 5     #默认3秒;初始下载延迟时间
AUTOTHROTTLE_MAX_DELAY = 180       #默认60秒;在高延迟情况下最大的下载延迟
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0   # 设置 Scrapy应该与远程网站并行发送的平均请求数, 目前是以1个并发请求数
MEDIA_ALLOW_REDIRECTS =True       # 允许重新定向(转到其他网址)
DOWNLOAD_WARNSIZE = 0             # 取消最大字节数限制
CONCURRENT_REQUESTS=10            # 并发设置为100
COOKIES_ENABLED=False             # 禁止cookie  在settings里设置默认cookie(从浏览器复制一下,或者bp抓包)
RETRY_ENABLED=False               # 打开重试开关
RETRY_TIMES=3                     # 重试次数
RETRY_HTTP_CODES = [429,404,403]  #重试对象
HTTPERROR_ALLOWED_CODES = [429]   #上面报的是403,就把403加入
DOWNLOAD_TIMEOUT=200               # 超时时间为20s
IMAGES_EXPIRES = 90               # 90天的图片失效期限
FILES_EXPIRES = 90                # 90天的文件失效期限
#LOG_LEVEL = 'ERROR'              # 日志只保留错误信息

#配置文件下载路径
import os
#FILES_STORE=os.path.join(os.path.dirname(os.path.dirname(__file__)),'文件下载路径')
FILES_STORE=os.path.join('D:\\siren','文件下载路径')

#配置图片下载路径
import os
#IMAGES_STORE=os.path.join(os.path.dirname(os.path.dirname(__file__)),'图片下载路径')
IMAGES_STORE=os.path.join('D:\\siren','图片下载路径')

(2)激活管道(图片下载管道和文件下载管道)
ITEM_PIPELINES = {
       'scrapy.pipelines.images.ImagesPipeline': 1   #默认图片下载渠道
       'scrapy.pipelines.files.FilesPipeline': 1     #默认文件下载渠道
       'BMW.pipelines.***ImagesPipeline': 1          #自定义的图片下载渠道  宝马5系   与pipelines中的自定义类相对应
       'mp3.pipelines.***FilesPipeline': 300,        #自定义的文件下载渠道  mp3
   }

(3)激活随机请求头

DOWNLOADER_MIDDLEWARES = {
   '***.middlewares.UserAgentDownloadMiddleware': 543,
}

3、修改items

所需的字段=scrapy.Field()  如  name=scrapy.Field()

#文件
category = scrapy.Field()   #文件夹名称
file_urls=scrapy.Field()
files=scrapy.Field()

#图片
category = scrapy.Field()   #文件夹名称
image_urls=scrapy.Field()
images=scrapy.Field()

4、修改pipelines

定义3个函数

#保存文本
from scrapy.exporters import JsonLinesItemExporter
class ***Pipeline:
    def open_spider(self,spider):
        self.fp=open("XXXXXXXXX.json",'wb')     #保存的文件名称
        self.exporter=JsonLinesItemExporter(self.fp,ensure_ascii=False,encoding='utf-8')
    def process_item(self, item, spider):
        self.exporter.export_item(item)        #以export方式导出,不以json方式导出
        return item
    def close_spider(self,spider):
        self.fp.close()
        print('爬虫结束....')

保存图片

from scrapy.pipelines.images import ImagesPipeline
from scrapy.pipelines.files import FilesPipeline
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from . import settings
import os
#(1)、重新构建类(自定义)
class ***ImagesPipeline(ImagesPipeline):
    def get_media_requests(self, item, info):
        #将item与request进行绑定,用于获取 items 中的分类(category)
        #这个方法是在发送下载请求前调用(这个函数本身就是去发送下载请求的)
        request_objs=super(***ImagesPipeline,self).get_media_requests(item,info)
        for request_obj in request_objs:
            request_obj.item=item
        return request_objs
    def  file_path(self, request, response=None, info=None):
        # 这个方法是在图片将要被存储的时候调用,来获取这个图片存储的路径
        path=super(***ImagesPipeline,self).file_path(request,response,info)
        category=request.item.get('category') .replace('/','').replace('\','').replace(':','').replace('*','').replace('?','').replace('"','').replace('<','').replace('>','').replace('|','').replace(' ','') # 获取分类并规范名称
        images_store=settings.IMAGES_STORE     # 获取图片保存路径
        category_path=os.path.join(images_store,category)   #拼接文件夹路径
        if not os.path.exists(category_path):
            os.mkdir(category_path)
        image_name=path.replace("full/","")   #获取图片名称
        image_path=os.path.join(category_path,image_name)
        print('开始爬取:    {}'.format(image_path))
        return image_path

保存文件(分目录存储)

   from scrapy.pipelines.images import ImagesPipeline
from scrapy.pipelines.files import FilesPipeline
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from . import settings
import os
#(1)、重新构建类(自定义)
class ***FilesPipeline(FilesPipeline):
    def get_media_requests(self, item, info):
        #将item与request进行绑定,用于获取 items 中的分类(category)
        #这个方法是在发送下载请求前调用(这个函数本身就是去发送下载请求的)
        request_objs=super(***FilesPipeline,self).get_media_requests(item,info)
        for request_obj in request_objs:
            request_obj.item=item
        return request_objs
    def  file_path(self, request, response=None, info=None):
        # 这个方法是在图片将要被存储的时候调用,来获取这个图片存储的路径
        path=super(***FilesPipeline,self).file_path(request,response,info)      #文件名称-哈希编码 full/512f6cb1745800a2176e793fb449c3b90e676efa.wav
        category=request.item.get('category') .replace('/','').replace('\\','').replace(':','').replace('*','').replace('?','').replace('"','').replace('<','').replace('>','').replace('|','').replace(' ','') # 获取分类并规范名称
        images_store=settings.FILES_STORE     # 获取文件保存路径
        category_path=os.path.join(images_store,category)   #拼接文件夹路径
        #category_path=os.path.join(images_store)           #文件路径可进行修改,取消文件夹,直接存到默认目录中
        if not os.path.exists(category_path):
            os.mkdir(category_path)
        image_name=path.replace("full/","")   #获取图片名称
   #  文件路径可进行修改,取消文件夹,直接存到默认目录中
    #  img_path=path.split(".")[:-1]
    #  image_name=path.replace(img_path[0],category)
    image_path=os.path.join(category_path,image_name)
    print('开始爬取:    {}'.format(image_path))
    return image_path

保存文件(默认目录存储)

   from scrapy.pipelines.images import ImagesPipeline
from scrapy.pipelines.files import FilesPipeline
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from . import settings
import os
#(1)、重新构建类(自定义)
class ***FilesPipeline(FilesPipeline):
    def get_media_requests(self, item, info):
        #将item与request进行绑定,用于获取 items 中的分类(category)
        #这个方法是在发送下载请求前调用(这个函数本身就是去发送下载请求的)
        request_objs=super(***FilesPipeline,self).get_media_requests(item,info)
        for request_obj in request_objs:
            request_obj.item=item
        return request_objs
    def  file_path(self, request, response=None, info=None):
        # 这个方法是在图片将要被存储的时候调用,来获取这个图片存储的路径
        path=super(***FilesPipeline,self).file_path(request,response,info)      #文件名称-哈希编码 full/512f6cb1745800a2176e793fb449c3b90e676efa.wav
        category=request.item.get('category') .replace('/','').replace('\\','').replace(':','').replace('*','').replace('?','').replace('"','').replace('<','').replace('>','').replace('|','').replace(' ','') # 获取分类并规范名称
        images_store=settings.FILES_STORE     # 获取文件保存路径
        #category_path=os.path.join(images_store,category)   #拼接文件夹路径
        category_path=os.path.join(images_store)           #文件路径可进行修改,取消文件夹,直接存到默认目录中
        if not os.path.exists(category_path):
            os.mkdir(category_path)
        #image_name=path.replace("full/","")   #获取图片名称
       #  文件路径可进行修改,取消文件夹,直接存到默认目录中
        img_path=path.split(".")[:-1]
        image_name=path.replace(img_path[0],category)
        image_path=os.path.join(category_path,image_name)
        print('开始爬取:    {}'.format(image_path))
        return image_path

6、修改爬虫

普通爬虫

from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
import scrapy,requests
from ..items import  ***Item

class KekemeinvSpider(scrapy.Spider):
    name = 'kekemeinv'
    allowed_domains = ['www.keke234.com']
    # 从start_requests发送请求
def start_requests(self):
    page_list = ['http://mobilecdngz.kugou.com/api/v3/rank/song?rankid=8888&ranktype=2&page={}&pagesize=30&volid=&plat=2&version=8955&area_code=1'.format(i) for i in range(1, 30)]
    for page_url in page_list:
        yield scrapy.Request(url=page_url,callback=self.parse_page)
def parse_page(self,response)
    url_list=response.xpath('//*[@id="a_ajax_5217174"]/@href').getall()
    for url in url_list:
        page_url='https://fj.91dfjh.pw/pw/'+url
        yield scrapy.Request(url=page_url, callback=self.parse_item)
def parse_item(self, response):
    #实例化item ,实现参数共享
    item=*****Item()
    item['category']=response.xpath('/html/body/main/div/div[1]/div[2]/div[1]/p/text()').get()
    mp3_url='https://www.kugou.com/yy/index.php?r=play/getdata&hash={}&album_id={}'.format(hash,album_id)
    yield scrapy.Request(url=mp3_url, callback=self.parse_detail, meta={"item": item})
def parse_detail(self,response):
    #承接item传递过来的参数
    item = response.meta['item']
    down_urls=response.xpath('//*[@id="cms_player"]/iframe/@src').getall()
    item["file_urls"] = down_urls
    yield item

规则爬虫

import scrapyfrom scrapy.linkextractors import LinkExtractorfrom scrapy.spiders import CrawlSpider, Rulefrom ..items import ***Itemclass Mymp3Spider(CrawlSpider):    name = 'mymp3'    allowed_domains = ['sc.chinaz.com']    start_urls = ['http://sc.chinaz.com/yinxiao/index_2.html']    rules = (        Rule(LinkExtractor(allow=r'http://sc.chinaz.com/yinxiao/\d+\.htm'),  follow=False),                          #列表页无需回调        Rule(LinkExtractor(allow=r'http://sc.chinaz.com/yinxiao/\d+\.htm'), callback='parse_item', follow=False),  #详情页需要回调    )def parse_item(self, response):    item = {}    category = response.xpath('//h2/a/text()').get()    # category  文件夹名称,单个文本    urls = response.xpath('//div[2]/div[1]/div[1]/div[3]/a[1]/@href').getall()  # urls  图片下载地址,列表    urls = list(map(lambda url: response.urljoin(url), urls))  # 循环遍历urls,并将结果以列表的形式传入    item = **Item(category=category, file_urls=urls)  # 不用字典,用Item格式回传到items    yield item

三、运行爬虫

1、start.py 直接运行
2、命令行:scrapy crawl 爬虫的名称 scrapy crawl 爬虫的名称 -o 保存的文件名

#####################################
POST请求
1、推荐使用 scrapy .FormRequest 方法,方便的制定表单数据
2、重写 start_requests 方法,在这个方法中,发送post请求

【gif图片下载】

(1) scrapy.pipelines.images.py 文件中的 ImagesPipeline 类,继承ImagesPipeline类后,对image_downloaded方法进行重写

def check_gif(self, image):    if image.format is None:        return Truedef persist_gif(self, key, data, info):    root, ext = os.path.splitext(key)    absolute_path = self.store._get_filesystem_path(key)    self.store._mkdir(os.path.dirname(absolute_path), info)    f = open(absolute_path, 'wb')  # use 'b' to write binary data.    f.write(data)def image_downloaded(self, response, request, info):    try:        checksum = None        for path, image, buf in self.get_images(response, request, info):            if checksum is None:                buf.seek(0)                checksum = md5sum(buf)            width, height = image.size            if self.check_gif(image):                self.persist_gif(path, response.body, info)            else:                self.store.persist_file(                    path, buf, info,                    meta={'width': width, 'height': height},                    headers={'Content-Type': 'image/jpeg'})            return checksum    except:        pass

(2)修改 pipelines.py

import scrapy,osfrom scrapy.utils.misc import md5sumfrom scrapy.pipelines.images import ImagesPipelinefrom . import settingsclass ***ImagesPipeline(ImagesPipeline):    def get_media_requests(self, item, info):        #将item与request进行绑定,用于获取 items 中的分类(category)        #这个方法是在发送下载请求前调用(这个函数本身就是去发送下载请求的)        request_objs=super(***ImagesPipeline,self).get_media_requests(item,info)        for request_obj in request_objs:            request_obj.item=item        return request_objs    def  file_path(self, request, response=None, info=None):        # 这个方法是在图片将要被存储的时候调用,来获取这个图片存储的路径        path=super(***ImagesPipeline,self).file_path(request,response,info)        #print(path)        category=request.item.get('category')  # 获取分类        images_store=settings.IMAGES_STORE     # 获取图片保存路径        category_path=os.path.join(images_store)            # 默认目录存储 路径        category_path=os.path.join(images_store,category)   # 分目录存储 路径        #print(category_path)        if not os.path.exists(category_path):            os.mkdir(category_path)        image_name=path.replace("full/","") .replace("jpg","gif")  #获取图片名称,并替换为gif格式        #image_name="{}.gif".format(category)        image_path=os.path.join(category_path,image_name)        #print(image_path)        return image_path    def check_gif(self, image):        if image.format is None:            return True    def persist_gif(self, key, data, info):        root, ext = os.path.splitext(key)        absolute_path = self.store._get_filesystem_path(key)        self.store._mkdir(os.path.dirname(absolute_path), info)        f = open(absolute_path, 'wb')  # use 'b' to write binary data.        f.write(data)    def image_downloaded(self, response, request, info):        try:            checksum = None            for path, image, buf in self.get_images(response, request, info):                if checksum is None:                    buf.seek(0)                    checksum = md5sum(buf)                width, height = image.size                if self.check_gif(image):                    self.persist_gif(path, response.body, info)                else:                    self.store.persist_file(                        path, buf, info,                        meta={'width': width, 'height': height},                        headers={'Content-Type': 'image/jpeg'})                return checksum        except:            pass

###############################################################

5、修改下载器中间件middlewares(设置随机请求头)

(1)、重新定义下载器中间件(middlewares)

user-agent 设置随机的请求头中间键

from fake_useragent import UserAgentclass UserAgentDownloadMiddleware(object):def process_request(self,request,spider):    user_agent=str(UserAgent().random)    request.headers['User-Agent']=user_agent    #print(request.headers['User-Agent'])

设置中间键破解防盗链接

class ReferMiddleWare(object):

def process_request(self,request,spider):    refer=request.url    if refer:        request.headers['refer']=refer        #print(request.headers['refer'])

proxy 设置随机的代理IP

class IPMiddleWare(object):    PROXIES = [    'http://171.11.178.36:9999',    'http://36.249.49.30:9999',    'http://124.65.136.2:8060',    'http://163.204.247.73:9999',    'http://163.204.241.89:9999',    'http://58.254.220.116:53579',    'http://122.5.107.51:9999'    ]    def process_request(self,request,spider):        proxy = random.choice(self.PROXIES)        request.meta['proxy'] = proxy

(2)、设置管道程序(setting)

DOWNLOADER_MIDDLEWARES = {    '***.middlewares.ReferMiddleWare': 1,    '***.middlewares.UserAgentDownloadMiddleware': 543,    '***.middlewares.IPMiddleWare': 200,}

scrapy_crawlscrapy

scrapy框架

什么是框架?
就是一个集成了很多功能并且具有很强通用性的一个项目模板。

如何学习框架?
专门学习框架封装的各种功能的详细用法。

什么是scrapy?
爬虫中封装好的一个明星框架。功能:高性能的持久化存储,异步的数据下载,高性能的数据解析,分布式

scrapy框架的基本使用

环境的安装:

​ mac or linux:pip install scrapy
​ windows:

pip install wheel

​ 下载twisted,下载地址为http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
​ 安装twisted:pip install Twisted‑17.1.0‑cp36‑cp36m‑win_amd64.whl
​ pip install pywin32
​ pip install scrapy
​ 测试:在终端里录入scrapy指令,没有报错即表示安装成功!
​ 创建一个工程:scrapy startproject xxxPro
​ cd xxxPro
​ 在spiders子目录中创建一个爬虫文件
​ scrapy genspider spiderName www.xxx.com
​ 执行工程:
​ scrapy crawl spiderName

scrapy数据解析

scrapy持久化存储
基于终端指令:
要求:只可以将parse方法的返回值存储到本地的文本文件中
注意:持久化存储对应的文本文件的类型只可以为:'json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle
指令:scrapy crawl xxx o filePath
好处:简介高效便捷
缺点:局限性比较强(数据只可以存储到指定后缀的文本文件中)

  基于管道:
      编码流程:
          数据解析
          在item类中定义相关的属性
          将解析的数据封装存储到item类型的对象
          将item类型的对象提交给管道进行持久化存储的操作
          在管道类的process_item中要将其接受到的item对象中存储的数据进行持久化存储操作
          在配置文件中开启管道
      好处:
          通用性强。

  面试题:将爬取到的数据一份存储到本地一份存储到数据库,如何实现?
      管道文件中一个管道类对应的是将数据存储到一种平台
      爬虫文件提交的item只会给管道文件中第一个被执行的管道类接受
      process_item中的return item表示将item传递给下一个即将被执行的管道类

基于Spider的全站数据爬取

​ 就是将网站中某板块下的全部页码对应的页面数据进行爬取
​ 需求:爬取校花网中的照片的名称
​ 实现方式:
​ 将所有页面的url添加到start_urls列表(不推荐)
​ 自行手动进行请求发送(推荐)

手动请求发送:

​ yield scrapy.Request(url,callback):callback专门用做于数据解析

五大核心组件

​ 引擎(Scrapy)
​ 用来处理整个系统的数据流处理, 触发事务(框架核心)
​ 调度器(Scheduler)
​ 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
​ 下载器(Downloader)
​ 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
​ 爬虫(Spiders)
​ 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
​ 项目管道(Pipeline)
​ 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。

请求传参

​ 使用场景:如果爬取解析的数据不在同一张页面中。(深度爬取)
​ 需求:爬取boss的岗位名称,岗位描述

图片数据爬取之ImagesPipeline
基于scrapy爬取字符串类型的数据和爬取图片类型的数据区别?
字符串:只需要基于xpath进行解析且提交管道进行持久化存储
图片:xpath解析出图片src的属性值。单独的对图片地址发起请求获取图片二进制类型的数据

  ImagesPipeline:
      只需要将img的src的属性值进行解析,提交到管道,管道就会对图片的src进行请求发送获取图片的二进制类型的数据,且还会帮我们进行持久化存储。
  需求:爬取站长素材中的高清图片
  使用流程:
      数据解析(图片的地址)
      将存储图片地址的item提交到制定的管道类
      在管道文件中自定制一个基于ImagesPipeLine的一个管道类
          get_media_request
          file_path
          item_completed
      在配置文件中:
          指定图片存储的目录:IMAGES_STORE = './imgs_bobo'
          指定开启的管道:自定制的管道类

中间件

​ 下载中间件
​ 位置:引擎和下载器之间
​ 作用:批量拦截到整个工程中所有的请求和响应
​ 拦截请求:
​ UA伪装:process_request
​ 代理IP:process_exception:return request

      拦截响应:
          篡改响应数据,响应对象
          需求:爬取网易新闻中的新闻数据(标题和内容)
              1.通过网易新闻的首页解析出五大板块对应的详情页的url(没有动态加载)
              2.每一个板块对应的新闻标题都是动态加载出来的(动态加载)
              3.通过解析出每一条新闻详情页的url获取详情页的页面源码,解析出新闻内容

CrawlSpider:类,Spider的一个子类
全站数据爬取的方式
基于Spider:手动请求
基于CrawlSpider

CrawlSpider的使用:

​ 创建一个工程
​ cd XXX
​ 创建爬虫文件(CrawlSpider):
​ scrapy genspider t crawl xxx www.xxxx.com
​ 链接提取器:
​ 作用:根据指定的规则(allow)进行指定链接的提取
​ 规则解析器:
​ 作用:将链接提取器提取到的链接进行指定规则(callback)的解析
​ #需求:爬取sun网站中的编号,新闻标题,新闻内容,标号
​ 分析:爬取的数据没有在同一张页面中。
​ 1.可以使用链接提取器提取所有的页码链接
​ 2.让链接提取器提取所有的新闻详情页的链接

分布式爬虫

​ 概念:我们需要搭建一个分布式的机群,让其对一组资源进行分布联合爬取。
​ 作用:提升爬取数据的效率

  如何实现分布式?
      安装一个scrapy redis的组件
      原生的scarapy是不可以实现分布式爬虫,必须要让scrapy结合着scrapy redis组件一起实现分布式爬虫。
      为什么原生的scrapy不可以实现分布式?
          调度器不可以被分布式机群共享
          管道不可以被分布式机群共享
      scrapy redis组件作用:
          可以给原生的scrapy框架提供可以被共享的管道和调度器
      实现流程
          创建一个工程
          创建一个基于CrawlSpider的爬虫文件
          修改当前的爬虫文件:
              导包:from scrapy_redis.spiders import RedisCrawlSpider
              将start_urls和allowed_domains进行注释
              添加一个新属性:redis_key = 'sun' 可以被共享的调度器队列的名称
              编写数据解析相关的操作
              将当前爬虫类的父类修改成RedisCrawlSpider
          修改配置文件settings
              指定使用可以被共享的管道:
                ITEM_PIPELINES = {
                    'scrapy_redis.pipelines.RedisPipeline': 400
                }
              指定调度器:
                # 增加了一个去重容器类的配置, 作用使用Redis的set集合来存储请求的指纹数据, 从而实现请求去重的持久化
                DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
                # 使用scrapy redis组件自己的调度器
                SCHEDULER = "scrapy_redis.scheduler.Scheduler"
                # 配置调度器是否要持久化, 也就是当爬虫结束了, 要不要清空Redis中请求队列和去重指纹的set。如果是True, 就表示要持久化存储, 就不清空数据, 否则清空数据
                SCHEDULER_PERSIST = True
              指定redis服务器:

          redis相关操作配置:
              配置redis的配置文件:
                  linux或者mac:redis.conf
                  windows:redis.windows.conf
                  代开配置文件修改:
                      将bind 127.0.0.1进行删除
                      关闭保护模式:protected mode yes改为no
              结合着配置文件开启redis服务
                  redis server 配置文件
              启动客户端:
                  redis cli
          执行工程:
              scrapy runspider xxx.py
          向调度器的队列中放入一个起始的url:
              调度器的队列在redis的客户端中
                  lpush xxx www.xxx.com
          爬取到的数据存储在了redis的proName:items这个数据结构中
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇