python爬虫复习 根据视频整理https://www.bilibili.com/video/BV12E411A7ZQ?p=3
01 02 python介绍和环境安装https://www.bilibili.com/video/BV12E411A7ZQ?p=3
python是解释型、面向对象的高级语言(与java不同,java需要编译生成中间状态,再运行中间状态的文件生成一个中间文件),python写完后就执行的解释型语言。
面向对象特点:封装继承和多态。
优点如下:
缺点如下:运行速度慢 代码不能加密:
02第一个python程序
exit()
或CTRL+z
可以退出python在命令提示符下的方式
在f盘中用记事本写print(‘hello ppp’)
且在cmd中打开
f:
python hello.py
4.用Pycharm编写程序
setting-editor-file and code templates
#-*- codeing = utf-8 -*-
#@Time ${DATE} ${TIME}
#@Author:sueong
#File:${NAME}.py
#@Software:${PRODUCT_NAME}
print(‘hello world’)
#这是单行注释
'''
1
2
3
这是多行注释
'''
格式化输出
age=15
print('我今年%d岁'%age)#%d占位 %age的值替代%d的位置
print('我今年',age,'岁')#,相当于空格分割
print('我的名字是%s,我的国籍是%s'%('小苏','中国'))
print('www','baidu','com',sep='.')#sep表示字符串之间用点分割
print('hello',end='')#end里面什么都不写表示不换行
print('world',end='\t')#end里面\t 一个tab
print('ccc',end='\n')#\n换行
print('end')#没有写end默认换行
05条件语句的判断
输入:
`
password=input('请输入您的密码:')
print('您的密码是:',password)
print(type(password))#证明input输入的都是str类型 虽然123456是数字但是是被当做字符串 如果需要数字可以强制类型转换
c=int(input("输入c:"))
print("输入了一个数字:%d",%c)
条件判断
tab前进一个tab tab+shift后缩一个tab
if 条件1:
执行语句1
elif 条件2:
执行语句2
else:
执行语句3
missing whitespace around operator#警告 操作符前后缺少空格 =等符号前后加空格即可
score = 55
if score >= 90:
c = 'A'
elif 80<=score<90:
c = 'B'
elif 60<=score<80:
c='C'
else:
c='D'
print("您的考试成绩等级是%s"%c)
import random
x=random.randint(0,10)#生成随机整数[0,10] 包含0和10
print(x)
#剪刀石头布(分别是0 1 2)
import random
x=random.randint(0,2)
num=int(input('请输入一个数字:'))
if 0<=num<=2:
flag=1
else:
flag=0
if flag:
if num==0:
print('您的输入为:剪刀(0)')
elif num==1:
print('您的输入为:石头(1)')
else:
print('您的输入为:步(2)')
print('随机生成的数为:%d'%x)
if num==0:
if x==0:
print('平局')
elif x==1:
print('输了')
else:
print('赢了')
elif num==1:
if x==0:
print('赢了')
elif x==1:
print('平局了')
else:
print('输了')
else:
if x==0:
print('输了')
elif x==1:
print('赢了')
else:
print('平局')
else:
print('您输入的数字范围错误请重新输入')
或者简化
#剪刀石头布(分别是0 1 2)
import random
x=random.randint(0,2)
num=int(input('请输入一个数字:'))
if 0<=num<=2:
flag=1
else:
flag=0
if flag:
if num==0:
print('您的输入为:剪刀(0)')
elif num==1:
print('您的输入为:石头(1)')
else:
print('您的输入为:步(2)')
print('随机生成的数为:%d'%x)
if num==x:
print('平局')
elif num>x:#有1-0 2-0(不可) 2-1
if num==2:#所以单独扣除2-0的情况
print('输了')
else:
print('赢了')
else:#就是num<x 的情况 0-1 1-2 0-2(不可 赢了)
if num==0:
print('赢了')
else:
print('输了')
else:
print('您输入的数字范围错误请重新输入')
06循环语句
for循环可以吧list或者tuple的元素列出来
```bash
for i in range(5):#默认从[0,5)
print(i)
print('————————————————————————————————')
for i in range(0,10,3):#从[0,10) 步长是3 每次加3
print(i)
print('————————————————————————————————')
for i in range(-10,-100,-30):#从(-100,-10] 每次-30
print(i)
print('————————————————————————————————')
name='fionaxixi'
for i in name:
print(i,end='\t')
a=['AA','BB','CC','DD']
for i in range(len(a)):
print(i,a[i])#i是下标 a[i]是列表元素
1-100求和
i=1
s=0
while i<=100:
s+=i
i+=1
print('1-100的和为%d'%s)
while可以和else连用
while 条件:
执行语句
else:
break continue pass语句
pass是空语句只占位 什么都不执行
continue处打印的是3 5 7 9
用for和while打印九九乘法表
for i in range (1,10):
for j in range(1,i+1):
print("%d*%d=%d"%(i,j,i*j),end=' ')
print('\n')
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
07字符串
但是尽量使用双引号 三引号可以写多行语句但是可以换行
str='I \'m a student'#\' 加\将'解释为普通的' 而不是结束的符号
print(str)
所以最好用"" 这样比较方便
str=“I 'm a student”
str="chengdu"
print(str)
print(str[0:5])
print(str[1:7:2])#[起始位置:结束位置:步进值] [1,7)
print(str[5:])
print(str[:5])
print(str+',你好')
print(str*3) #打印三次str
print("hello\nworld")#\n 换行
print(r"hello\nworld")#加了r 使转义消失 直接打出\n
08列表 list
像数组,但是列表中的每个元素的数据类型可以不同,可以混合类型
列表的遍历
namelist=['小吴','小明','小陈']
for name in namelist:
print(name)
小吴
小明
小陈
**【增】**append extend insert
a=[1,2]
b=[3,4]
a.append(b)#是把b当成整体放入a
print(a)
a.extend(b)
print(a)#extend是把b的每个元素逐一加入a
[1, 2, [3, 4]]
[1, 2, [3, 4], 3, 4]
a=[0,1,2]
a.insert(1,3)#(pos,val)
print(a)
[0, 3, 1, 2]
【删】 del pop remove
a=[0,1,2,3,4,3]
del a[0]#删除指定位置元素
print(a)
a.remove(3)#删除符合的第一个指定值val元素 没找到会报错 ValueError: list.remove(x): x not in list
print(a)
a.pop()#删除末尾元素
print(a)
[1, 2, 3, 4, 3]
[1, 2, 4, 3]
[1, 2, 4]
09 列表(下)
【改】
a[1]=2 #修改指定下标的元素
【查】 in,not in ,index
a=[0,1,2,3,4,3]
x=int(input('输入你要查找的数字:'))
if x in a:
print('YES')
else:
print('No')
输入你要查找的数字:1
YES
a=['aaa','bbb','ccc','aaa','bbb']
print(a.index('aaa',1,4))#在[1,4)间有无aaa这个字符串 index找指定范围的内的元素是否存在 并且返回找的元素的下标
#找不到会报错
3
【排序和反转】
a=[4,2,1,3]
a.reverse()#逆序
print(a)
a.sort()#升序
print(a)
a=[4,2,1,3]
a.sort(reverse=True)#降序排列
print(a)
[3, 1, 2, 4]
[1, 2, 3, 4]
[4, 3, 2, 1]
school=[['beida','qinghua'],['nankai','tianda','waiguoyu']]
print(school[0][1])
print(school[0])
qinghua
['beida', 'qinghua']
#八个老师随机分三个办公室
import random
offices=[[],[],[]]#列表中有三个空列表作为元素
names=['A','B','C','D','E','F','G','H']
for name in names:
index=random.randint(0,2)#随机生成一个编号
offices[index].append(name)#将名字放到对应的办公室编号处
i=1
for office in offices:
print('办公室%d的人数有:%d'%(i,len(office)))
i+=1
for name in office:#这个办公室的人员有
print('%s'%name,end='\t')
print('\n')
办公室1的人数有:3
E G H
办公室2的人数有:2
A D
办公室3的人数有:3
B C F
# -*- codeing = utf-8 -*-
# @Time :2021/2/9 17:01
# @Author:sueong
# @File:demo7.py
# @Software:PyCharm
products=[['iphone',6888],['mac',14800],['小米6',2499],['coffee',31],['book',60],['nike',699]]
i=0
print('--------商品列表---------')
for p in products:
print("%d %s %-d"%(i,products[i][0],products[i][1]))
i+=1
buylist=[[],[],[],[],[],[]]
i=0
while 1:
x =(input("请输入您想要买的商品编号:"))
if x=='q':
print('购买结束')
break
else:
x=int(x)
if x<0 or x>6:
print('请输入正确编号')
else:
buylist[i].append(x)#buylist 中的每个元素有编号 名称 价格
buylist[i].extend(products[x])
i+=1
i=0
for b in buylist:
if b:#如果b不是空列表打印
#print(buylist[i])直接打印是列表有带[]
print("%d %s %d" % (buylist[i][0], buylist[i][1], buylist[i][2]))
i += 1
--------商品列表---------
0 iphone 6888
1 mac 14800
2 小米6 2499
3 coffee 31
4 book 60
5 nike 699
请输入您想要买的商品编号:4
请输入您想要买的商品编号:5
请输入您想要买的商品编号:1
请输入您想要买的商品编号:q
购买结束
4 book 60
5 nike 699
1 mac 14800
10元祖
tuple与list类似 但是元祖内的元素不可以修改 写在()内,但是()里的对象可变,如list[],元素之间用逗号隔开,注意:定义只有一个元素的tuple时必须加逗号 如下所示
tup=('ABC','DDD','EEE',2001,2002)
print(tup[-1])#打印的是最后一个
print(tup[1:5])#左闭右开 [1:5)
2002
('DDD', 'EEE', 2001, 2002)
#增
tup1=(12,34,56)
tup2=('abc','efd')
tup=tup1+tup2
print(tup)
# 删
tup1=(12,34,56)
print(tup1)
del tup1 #删除整个元祖对象 但是不能删除元祖内的某个元素
print(tup1)
print('删除后:')# 报错 NameError: name 'tup1' is not defined
print(tup1)
# 改
tup1=(12,34,56)
tup1[0]=100
print(tup1)#报错 不能修改
# 查
11字典dict
存储的是key-value key是唯一的
字典的访问:{'key':value}
info={'name':'fiona','age':18}
print(info['name'])
print(info['age'])
#print(info['gender'])#不存在 报错
print(info.get('gender'))#不存在 返回默认值none
print(info.get('age','20'))#如果age存在 则默认值20不起作用
fiona
18
None
18
#增
info={'name':'fiona','age':18}
newid=input("请输入您的学号")
info['id']=newid
print(info['id'])
'''
# 删 del or clear
info={'name':'fiona','age':18}
print('删除前:%s'%info['name'])
print('删除前:%s'%info)#打印整个字典 删除前:{'name':'fiona','age':18}
del info['name']
del info
print('删除后:%s'%info['name'])#删除的是整个键值对 会报错
print('删除前:%s'%info)#报错
info={'name':'fiona','age':18}
print('删除前:%s'%info)
info.clear()
print('删除后:%s'%info)#删除的是整个键值对 {} 不会报错
'''
删除前:{'name': 'fiona', 'age': 18}
删除后:{}
'''
# 查 ==遍历
info={'name':'fiona','age':18,'id':123456}
print(info.keys())# 得到所有的键 列表
print(info.values())# 得到所有的值 列表
print(info.items())#得到所有的项 列表 每个键值对是一个元祖
'''
dict_keys(['name', 'age', 'id'])
dict_values(['fiona', 18, 123456])
dict_items([('name', 'fiona'), ('age', 18), ('id', 123456)])
'''
#遍历
for key in info.keys():
print(key)
print('______________________')
for value in info.values():
print(value)
print('______________________')
for key,value in info.items():
print('key=%s,value=%s'%(key,value))
print('______________________')
mylist=['a','b','c','d']
for i,x in enumerate(mylist):#枚举函数 同时拿到下标和值
print(i,x)
删除前:{'name': 'fiona', 'age': 18}
删除后:{}
dict_keys(['name', 'age', 'id'])
dict_values(['fiona', 18, 123456])
dict_items([('name', 'fiona'), ('age', 18), ('id', 123456)])
name
age
id
______________________
fiona
18
123456
______________________
key=name,value=fiona
key=age,value=18
key=id,value=123456
______________________
0 a
1 b
2 c
3 d
集合set 不重复的元素 无序 会自动过滤重复元素([key1,key2,key3]) 打印出来是{key1,key2,key3}
12函数
def 函数名():
代码
#函数的定义
def printinfo():
print("____________")
print("i love python")
print("____________")
#函数的调用
printinfo()
printinfo()
#带参数的函数
def add(a,b):
c=a+b
print(c)
add(11,12)
#带返回值的参数
def add2(a,b):
return a+b
r=add2(10,15)
print(r)
#返回多个返回值的参数
def div(a,b):
shang=a/b
yushu=a%b
return shang,yushu#多个返回值用逗号分隔
sh,yu =div(5,2)#需要多个值来保存返回的内容
print('商:%d,余数:%d'%(sh,yu))
#函数的定义
def printinfo():
print("____________")
print("i love python")
print("____________")
#函数的调用
printinfo()
printinfo()
____________
i love python
____________
____________
i love python
____________
def printh():
print("___________")
def printh1(x):
while x:
printh()
x-=1
printh1(5)
def add(a,b,c):
return a+b+c
def ave(a,b,c):
return add(a,b,c)/3
print(ave(2,5,7))
___________
___________
___________
___________
___________
4.666666666666667
#全局变量和局部变量
#局部变量:在不同函数内可以定义相同的名字 彼此无关 仅仅定义在函数内部
#全局变量 定义在函数外
#如test1中有自己的变量a,所以访问自己的变量a test2中没有自己的变量a 所以访问全局变量100
在函数中修改全局变量 加上global
13 文件操作
# #read方法 读取指定的字符 开始时定位在文件的头部 每执行一次向后移动指定字符数
# f=open("test.txt","w") #打开文件 w模式(写模式) 文件不存在就新建在与当前文件同一目录下的路径
# f.write('hello world, i am here')#将字符串写进文件中
# f.close()#关闭文件
#
#
# f=open('test.txt','r')
# content=f.read(5)#读出hello
# print(content)
f=open('test.txt','r')
content=f.readlines()#一行一行读取出来 读出多行 读出整个文本
c=f.readline()#只能读出一行
print(content)
f.close()
'''
['hello world, i am here\n', 'hello world, i am here\n', 'hello world, i am here\n', 'hello world, i am here\n', 'hello world, i am here\n']
'''
14异常处理
找不到num这个值的异常是 nameError,要根据报错的类型 来捕获异常,所以异常类型想要被捕获需要一致
若是需要捕获多个异常写成
try:
代码
except (NameError,IOError,xxxx):#将可能出现的问题都放在这里
代码
#捕获异常
#或许错误的描述
try:
print('--------test-------1')
f=open('123.txt','r')
print('---------test------2')
except IOError as result:#文件没好到 属于IO异常(输入输出异常)
print(result)
'''
--------test-------1
[Errno 2] No such file or directory: '123.txt'
'''
try:
代码
except Exception as result: # Exception承接所有的异常
print(result)
#try finally 和嵌套
import time
try:
f=open('test.txt','r')
try:
while True:
content=f.readline()
if len(content)==0:
break
time.sleep(2)#休眠两秒 两秒打印一次
print(content)
finally:#如果在打开或读文件的过程中出现错误 反正一定会执行finally中的close
f.close()
print('文件关闭')
except Exception as result:
print('发生异常')
def writefile(filename,content):
f = open(filename, 'w')
for i in content:
f.write(i)
f.close()
def readFile(filename):
f=open(filename,'r')
contents=f.readlines()
return contents
f.close()
gushi = ["日照香炉生紫烟\n","遥看瀑布挂前川\n","飞流直下三千尺\n","疑似银河落九天\n"]
copy=[]
try:
writefile('gushi.txt', gushi)
contents = readFile('gushi.txt')
except Exception as result:
print(result)
finally:
print("结束运行")
for content in contents:
copy.append(content)
writefile('copy.txt', copy)
f=open('gushi1.txt','w',encoding='utf-8')
gushi = '日照香炉生紫烟\n遥看瀑布挂前川\n飞流直下三千尺\n疑似银河落九天\n'
f.write(gushi)
f=open('gushi1.txt','r',encoding='utf-8')
contents=f.read()#当时w时 会报错io.UnsupportedOperation: not readable
f.close()
newf=open('copy1.txt','w',encoding='utf-8')
newf.write(contents)
newf.close()
15爬虫
任务:爬取豆瓣top250的电影评价和信息
爬虫初始:
16准备工作
https://movie.douban.com/top250?start=25&filter=
25表示将25后面的第一个返回给你即返回第26个
Header中的Heade Responds是我们发给服务器的 告诉服务器返回的内容需要满足的适配条件,而真正的服务器发给我们的内容在Responds这里面的才是我们想要获取的,但是如果我们不给服务器发送对应的头部是无法获取的
当我们在浏览器中输入网址回车后,浏览器就像服务器发送了Headers中的文件
每次通过浏览器写一个网址访问的时候,浏览器就会带上这user-agent这样的信息发给服务器告诉他,你现在的浏览器版本是什么(Chrome80 系统是win10等等),你能接受什么样子的消息,浏览网页的时候服务器也在看你在干什么,知道你的行为。cookie是服务器为了标识每一个客户端的行为或登录信息,保存在本地的一些内容,是加密的,所以当我访问豆瓣时,cookie中包含了我的ip地址、以前访问的关键字、从哪个连接来的等等(所以要爬取登录以后的消息 要学会cookie)
Headers里面是我们向网页发起请求时候给服务器的消息,服务器通过里面的消息鉴定我们的身份,不管是登录的身份(在cookie内),还是在浏览器的身份(user-agent)
可以通过这个部分判断我们所需要的文字在哪个层级上
def main():
print("hello")
if __name__=="__main__":#当程序执行时 作为整个程序的入口
#调用函数
main()
模块的引用:
在test1文件夹内:
#test1内
def add(a,b):
return a+b
print(add(1,4))
#test2
#引入自定义模块
from test1 import t1
#引入系统的模块
import os
import sys
#引入第三方模块
import re
print(t1.add(3,6))
引入模块
import bs4 #网页解析获取数据
import re#正则表达式 文字匹配
import urllib.request,urllib.error
import xlwt #进行excel操作
import sqlite3 #进行SQLite数据库操作
18urllib补充
httpbin.org :
import urllib.request
#获取一个get请求
# response=urllib.request.urlopen("https://baidu.com")
# print(response.read().decode('utf-8'))#对获取的网页源码进行utf-8解码
#获取一个post请求 模拟用户登录请求
import urllib.parse#parse解析器
data=bytes(urllib.parse.urlencode({"hello":"world"}),encoding='utf-8')#以utf-8的方式封装成键值对,变成二进制数据传给data
response=urllib.request.urlopen('http://httpbin.org/post',data=data)
print(response.read().decode('utf-8'))
#get请求
#超时处理 就先不爬取了
try:
response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.01)
print(response.read().decode('utf-8'))
except urllib.error.URLError as e:
print('time out!')#表示来不及响应 0.01秒太短了
response = urllib.request.urlopen('http://httpbin.org/get')
print(response.status)#状态码 200
response = urllib.request.urlopen('http://baidu.com')
#print(response.status)#状态码 418 表示对方已经发现你是一个爬虫了
print(response.getheaders())#打印的是列表 请求的头部信息
print(response.getheader('Server'))#只获取一个具体的属性
模拟浏览器真实收到的样子
{
"args": {},
"data": "",
"files": {},
"form": {
"hello": "world"
},
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "11",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Python-urllib/3.7",
"X-Amzn-Trace-Id": "Root=1-60323922-4801b11d70334481598a1e00"
},
"json": null,
"origin": "120.42.187.23",
"url": "http://httpbin.org/post"
}
Process finished with exit code 0
418报错:网站识别出你是爬虫所以要把请求封装发
以百度为例子:https://www.baidu.com/
f12-network-刷新-出现线条波动–stop—点击蓝色线条–选择www.baidu.com—headers----User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
这就是我们要的存在header字典内
#伪装成浏览器
url='http://httpbin.org/post'
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
}
data=bytes(urllib.parse.urlencode({'name':'eric'}),encoding='utf-8')
req=urllib.request.Request(url=url,data=data,headers=headers,method='POST')#要把请求封装一下,headers是让服务器有针对性的把一些头部信息带回来 req是封装的对象
response=urllib.request.urlopen(req)#把封装好的req传进去 而不是直接打开url
print(response.read().decode('utf-8'))
{
"args": {},
"data": "",
"files": {},
"form": {
"name": "eric"
},
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "9",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
"X-Amzn-Trace-Id": "Root=1-6032471f-5d9648323d0e77ef60163306"
},
"json": null,
"origin": "120.42.187.23",
"url": "http://httpbin.org/post"
}
#伪装成浏览器 这样访问豆瓣不会报418的错
url='http://douabn.com'
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
}
#data=bytes(urllib.parse.urlencode({'name':'eric'}),encoding='utf-8')
req=urllib.request.Request(url=url,headers=headers)#要把请求封装一下,headers是让服务器有针对性的把一些头部信息带回来 req是封装的对象
response=urllib.request.urlopen(req)#把封装好的req传进去 而不是直接打开url
print(response.read().decode('utf-8'))
19数据获取
# -*- codeing = utf-8 -*-
# @Time :2021/2/19 19:36
# @Author:sueong
# @File:douban.py
# @Software:PyCharm
from bs4 import BeautifulSoup #网页解析获取数据
import re#正则表达式 文字匹配
import urllib.request,urllib.error
import xlwt #进行excel操作
import sqlite3 #进行SQLite数据库操作
def main():
baseurl='https://movie.douban.com/top250?start='
#1爬取网页
datalist=getData(baseurl)
savepath='.\\豆瓣电影top20.xls'
#2解析数据
#3保存数据
saveData(savepath)
askURL("https://movie.douban.com/top250?start=")
#1爬取网页
def getData(baseurl):
datalist=[]
for i in range(0,10):#左闭右开 调用获取信息页面的函数 10次
url=baseurl+str(i*25)
html=askURL(url)#保存获取到的网页原码
#2逐一解析数据 获取一个网页就要解析一次
return datalist
#得到指定一个url的网页内容
def askURL(url):
head = {# 模拟浏览器头部信息,向豆瓣服务器发送请求
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
}
#用户代理表示告诉豆瓣服务器,我们是什么类型的机器、浏览器,本质上是告诉浏览器我们可以接收什么水平的文件内容
request=urllib.request.Request(url,headers=head)#封装的请求
html=""
try:
response=urllib.request.urlopen(request)
html=response.read().decode('utf-8')
print(html)
except urllib.error.URLError as e:
if hasattr(e,'code'):
print(e.code)
if hasattr(e,'reason'):#hasattr是一个标签
print(e.reason)
return html
#保存数据
def saveData(savepath):
print('save...')
if __name__ == '__main__':#当程序执行时
main() #调用函数
20补充bs4(上 )
from bs4 import BeautifulSoup
file=open('./baidu.html','rb')
html=file.read()
#1 Tag 拿到是标签及其内容:拿到它所找到的第一个内容
bs=BeautifulSoup(html,'html.parser')#用解析器解析html bs是一个树形结构
print(bs.title)#打印<title></title>之间的内容 <title>百度一下,你就知道 </title>
print(bs.head)#打印<head></head>之间的内容
print(bs.a)#打印<a></a>之间的内容
print("-"*50)
#2NavigableString 标签的内容就是字符串
print(bs.title.string)
print(type(bs.title.string))
print(bs.a.attrs)#属性 用字典保存键值对
'''
百度一下,你就知道
<class 'bs4.element.NavigableString'>
{'class': ['mnav'], 'href': 'http://news.baidu.com', 'name': 'tj_trnews'}
'''
print("-"*50)
#3 BeautifulSoup 表示整个文档
print(type(bs))
print(bs.name)
print(bs.attrs)
print(bs)#打印的就是整个文档
'''
<class 'bs4.BeautifulSoup'>
[document]
{}
'''
#4Comment 是一种特殊的NavigableString 输出的内容不包括注释符号
print(bs.a.string)
print(type(bs.a.string))
'''
新闻
<class 'bs4.element.Comment'>
'''
#文档的遍历 相似的东西全部找到
print(bs.head.contents[1])
'''
<meta content="text/html;charset=utf-8" http-equiv="content-type"/>
'''
21补充bs4(下)
#文档的搜索
#1 find_all()
#字符串过滤:会查找与字符串完全匹配的内容
t_list=bs.find_all("a")#将a标签内所有的超链接都放在一个列表里
print(t_list)
print("--------------")
'''
[<a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!--新闻--></a>, <a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>, <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123</a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图</a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频</a>, <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧</a>, <a class="bri" href="//www.baidu.com/more/"
name="tj_briicon" style="display: block;">更多产品 </a>]
'''
import re
#正则表达式搜索:使用search()方法来匹配内容
t_list=bs.find_all(re.compile('a'))#正则表达式内 标签名称包含a的都会显示 如head meta a等 会将标签的内容一起打出来
print(t_list)
#——————————————————————————
#方法 :传入一个函数(方法) 根据函数的要求来搜索(了解)
def name_is_exists(tag):
return tag.has_attr('name')#传入一个tag 打印出这个含有name这个名字的标签
t_list=bs.find_all(name_is_exists)#只会打印出含有name=xxx 的标签内容
for i in t_list:#打印列表
print(i)
'''
<meta content="always" name="referrer"/>
<a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!--新闻--></a>
<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>
<a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123</a>
<a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图</a>
<a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频</a>
<a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧</a>
<a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
'''
#kwargs 参数
'''
t_list=bs.find_all(id='head')#可以给个参数
for i in t_list:
print(i)
把含有head包含进来
<div id="head">
<div class="head_wrapper">
<div id="u1">
<a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!--新闻--></a>
<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>
<a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123</a>
<a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图</a>
<a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频</a>
<a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧</a>
<a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
</div>
</div>
</div>
'''
# t_list=bs.find_all(class_=True)#class及其子内容
# for i in t_list:
# print(i)
#3text
#t_list=bs.find_all(text='hao123')#文本内容
t_list=bs.find_all(text=['hao123','地图','贴吧'])#文本内容
for i in t_list:
print(i)
'''
hao123
地图
贴吧
'''
print('_'*50)
t_list=bs.find_all(text=re.compile('\d'))#找所有含有数字的文本 正则表达式找包含特定文本的内容(标签里的字符串)
for i in t_list:
print(i)
#4 limit参数
t_list=bs.find_all('a',limit=3)#只找3个含有a的标签
for i in t_list:
print(i)
21补充正则表达式
正则表达式基本都是一位数
# -*- codeing = utf-8 -*-
# @Time :2021/3/1 20:16
# @Author:sueong
# @File:testre.py
# @Software:PyCharm
#正则表达式 :字符串模式(判断字符串是否符合一定的标准)
import re
#创建模式对象
pat=re.compile('AA')#AA是正则表达式 相当于是一个标准 用来验证其他的字符串
m=pat.search('CBA')#search字符串被校验的内容
print(m)#结果:None---不匹配
m=pat.search('ABCAA')#search字符串被校验的内容
print(m)#<re.Match object; span=(3, 5), match='AA'> 找到了匹配对象AA在[3,5)
m=pat.search('ABCAADDAAA')#search方法进行比对 查找
print(m)#span还是[3,5)
#没有模式对象
m=re.search('ABC','ABCDE')#简写 前面的字符串是规则(模板) 后面的字符串是被校验的对象
print(m)#<re.Match object; span=(0, 3), match='ABC'>
print(re.findall('a','ASDaDFGAa'))#前面是规则 后面是被校验的字符串
#['a', 'a'] 打印出列表 符合的列表
print(re.findall('[A-Z]','ASDADFaaac'))#表示要找到所有的大写字母 是一个一个字母
'''
['A', 'S', 'D', 'A', 'D', 'F']
'''
print(re.findall('[A-Z]+','ASDaDFGA'))#表示符合大写字母的多个字符串
'''
['ASD', 'DFGA']
'''
#sub 分割
print(re.sub('a','A','abcdcasd'))#找到a用A替换,在第三个字符串中查找
'''
AbcdcAsd
'''
#建议在正则表达式中,被比较的字符串前面加上r,不用担心转义字符的原因
a=r"\aabbc\'"
print(a)
'''
\aabbc\'
'''
23正则提取
可以找到更具体的span title下的文字 :肖申克的救赎
假设当我们需要找的是href的这个链接 我们可以通过正则表达式
发现这个规则都是
<a href="https://movie.douban.com/explore">
()表示一组数 .表示一个字符 *表示一个或多个字符 ?表示一次或0次
findlink=re.compile(r'<a href="(.*?)">')#创建或生成正则表达式对象 findlink是个规则标准(or字符串的模式)
#2逐一解析数据 获取一个网页就要解析一次
soup = BeautifulSoup(html,'html.parser')
for item in soup.find_all('div',class_='item'):
# 查找符合要求的字符串 形成列表 就是要找到所有class 是item同时于是div的内容 记得clas是个类别要加下划线 div同时有个class属性 div同时有个下划线属性这个属性是iem的内容
#print(item) #测试查看电影i的全部信息
data=[]#保存一部电影的所有信息
item=str(item)
link=re.findall(findlink,item)[0]#re库用来通过正则表达式查找指定的字符串 在findlink这个模式中中item符合条件的第一个就是我们要的内容
print(link)
link=re.findall(findlink,item)[0]#re库用来通过正则表达式查找指定的字符串 在findlink这个模式中中item符合条件的第一个就是我们要的内容
筛选出的连接
https://movie.douban.com/subject/1308767/
https://movie.douban.com/subject/1305690/
https://movie.douban.com/subject/25807345/
https://movie.douban.com/subject/1419936/
https://movie.douban.com/subject/2363506/
https://movie.douban.com/subject/26614893/
https://movie.douban.com/subject/1304102/
https://movie.douban.com/subject/1760622/
https://movie.douban.com/subject/1310177/
https://movie.douban.com/subject/1307106/
https://movie.douban.com/subject/1291568/
https://movie.douban.com/subject/1300117/
https://movie.douban.com/subject/2213597/
https://movie.douban.com/subject/1304141/
https://movie.douban.com/subject/6874403/
https://movie.douban.com/subject/1959877/
https://movie.douban.com/subject/25921812/
https://movie.douban.com/subject/5908478/
https://movie.douban.com/subject/1292528/
https://movie.douban.com/subject/2297265/
https://movie.douban.com/subject/25954475/
https://movie.douban.com/subject/26393561/
https://movie.douban.com/subject/1397546/
https://movie.douban.com/subject/1291824/
https://movie.douban.com/subject/27615441/
查找img的链接<img alt="谍影重重2" class="" src="https://img9.doubanio.com/view/photo/s_ratio_poster/public
findimgsrc=re.compile(r'img.*src="(.*?)"',re.S)#re.S让换行符包含在字符中
定义各种规则
from bs4 import BeautifulSoup #网页解析获取数据
import re#正则表达式 文字匹配
import urllib.request,urllib.error
import xlwt #进行excel操作
import sqlite3 #进行SQLite数据库操作
def main():
baseurl='https://movie.douban.com/top250?start='
#1爬取网页
datalist=getData(baseurl)
savepath='.\\豆瓣电影top20.xls'
#2解析数据
#3保存数据
saveData(savepath)
askURL("https://movie.douban.com/top250?start=")
#影片详情链接的规则
findlink=re.compile(r'<a href="(.*?)">')
#创建或生成正则表达式对象 findlink是个规则标准(or字符串的模式)
#影片图片
findimgsrc=re.compile(r'img.*src="(.*?)"',re.S)#re.S让换行符包含在字符中
#影片片名
findtitle=re.compile(r'<span class="title">(.*)</span>')
#影片评分
findrating=re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
#评价人数
findjudge=re.compile(r'<span>(\d*)人评价</span>')#0个或多个数字
#找到概况
findinq=re.compile(r'<span class="inq">(.*)</span>')
#影片信息
findBd=re.compile(r'<p class="">(.*)</p>',re.S)#因为该内容有换行符
24标签解析
25保存数据到excel
使用xlwt去对excel表格执行操作的时候,有个坑:
AttributeError: module ‘xlwt’ has no attribute 'Workbook’
解决方案:
1、文件名与导入的模块名不能一样。文件名不能为xlwt.py
2、Workbook里的那个W是大写的,应该是这样导入
workbook = xlwt.Workbook()
import xlwt
workbook=xlwt.Workbook(encoding='utf-8')#创建workbook对象
worksheet=workbook.add_sheet('sheet1')#创建工作表
worksheet.write(0,0,'hello')#在excel中写入数据 第一个表示行 第二个表示列
workbook.save('student.xls')#保存数据
九九乘法表
import xlwt
workbook=xlwt.Workbook(encoding='utf-8')#创建workbook对象
worksheet=workbook.add_sheet('sheet1')#创建工作表
for i in range(1,10):
for j in range(1,i+1):
worksheet.write(i-1,j-1, '%d*%d=%d'%(i,j,i*j)) # 在excel中写入数据 第一个表示行 第二个表示列
workbook.save('99.xls')#保存数据
报错:只能打印出226-250的影评且说列表超出范围
原因:for循环的缩进没弄好两个for循环不是并列的,开始时把两个for循环变成并列的了
# -*- codeing = utf-8 -*-
# @Time :2021/2/19 19:36
# @Author:sueong
# @File:douban.py
# @Software:PyCharm
from bs4 import BeautifulSoup #网页解析获取数据
import re#正则表达式 文字匹配
import urllib.request,urllib.error
import xlwt #进行excel操作
import sqlite3 #进行SQLite数据库操作
def main():
baseurl='https://movie.douban.com/top250?start='
#1爬取网页
datalist=getData(baseurl)
savepath='豆瓣电影top250.xls' #表示保存到当前路径
#2解析数据
#3保存数据
saveData(datalist,savepath)
#askURL("https://movie.douban.com/top250?start=")
#影片详情链接的规则
findlink=re.compile(r'<a href="(.*?)">')
#创建或生成正则表达式对象 findlink是个规则标准(or字符串的模式)
#影片图片
findimgsrc=re.compile(r'<img.*src="(.*?)"',re.S)#re.S让换行符包含在字符中
#影片片名
findtitle=re.compile(r'<span class="title">(.*)</span>')
#影片评分
findrating=re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
#评价人数
findjudge=re.compile(r'<span>(\d*)人评价</span>')#0个或多个数字
#找到概况
findinq=re.compile(r'<span class="inq">(.*)</span>')
#影片信息
findBd=re.compile(r'<p class="">(.*)</p>',re.S)#因为该内容有换行符
#1爬取网页
def getData(baseurl):
datalist=[]
for i in range(0,10):#左闭右开 调用获取信息页面的函数 10次
url=baseurl+str(i*25)
html=askURL(url)#保存获取到的网页原码
#2逐一解析数据 获取一个网页就要解析一次
soup = BeautifulSoup(html,'html.parser')
for item in soup.find_all('div',class_='item'):
# 查找符合要求的字符串 形成列表 就是要找到所有class 是item同时于是div的内容 记得clas是个类别要加下划线 div同时有个class属性 div同时有个下划线属性这个属性是iem的内容
#print(item) #测试查看电影item的全部信息
data=[]#保存一部电影的所有信息
item=str(item)
link=re.findall(findlink,item)[0]#re库用来通过正则表达式查找指定的字符串 在findlink这个模式中中item符合条件的第一个就是我们要的内容
data.append(link) #添加链接
imgsrc=re.findall(findimgsrc,item)[0]
data.append(imgsrc)#添加图片
titles=re.findall(findtitle,item)#片名可能只有一个中文名字,没有外文名字
if(len(titles) == 2):
ctitle=titles[0]#添加中文名
data.append(ctitle)
otitle=titles[1].replace('/','')#把外文前面的/号替换成空格或者没有
data.append(otitle)#添加外文名
else:
data.append(titles[0])
data.append(' ')#即使是只有中文名 无外文名 也要留着空的字符串
ratings=re.findall(findrating,item)[0]
data.append(ratings)#添加评分
judges=re.findall(findjudge,item)[0]
data.append(judges)#评价人数
inq=re.findall(findinq,item) #概述可能不存在
if(len(inq)!=0):
inq=inq[0].replace('。','')#去掉句号
data.append(inq)
else:
data.append(' ')#留空
bd=re.findall(findBd,item)[0]
bd=re.sub('<br(\s+)?/>(\s+)?'," ",bd)#替换掉</BR> (可能br内有其他的内容) /等不想要的字符
bd = re.sub('/', " ", bd)#替换/
data.append(bd.strip())#去掉bd前后的空格
datalist.append(data) #把处理好的每一部电影信息放在datalist
print(datalist)
return datalist
#得到指定一个url的网页内容
def askURL(url):
head = {# 模拟浏览器头部信息,向豆瓣服务器发送请求
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
}
#用户代理表示告诉豆瓣服务器,我们是什么类型的机器、浏览器,本质上是告诉浏览器我们可以接收什么水平的文件内容
request=urllib.request.Request(url,headers=head)#封装的请求
html=""
try:
response=urllib.request.urlopen(request)
html=response.read().decode('utf-8')
#print(html)
except urllib.error.URLError as e:
if hasattr(e,'code'):
print(e.code)
if hasattr(e,'reason'):#hasattr是一个标签
print(e.reason)
return html
#保存数据
def saveData(datalist,savepath):#把datalist的内容放进去
print('save...')
book=xlwt.Workbook(encoding='utf-8',style_compression=0)#创建workbook对象 样式压缩效果为0
sheet=book.add_sheet('豆瓣电影top250',cell_overwrite_ok=True)#创建表格,每个单元是否可以覆盖
col = ("电影详情链接","图片链接","影片中文名","影片外国名","评分","评价数","概况","相关信息")#定义了一个元组
for i in range(0,8):
sheet.write(0,i,col[i])#把列名称写进去
for i in range(0,250):#写入250条影评
print("第%d条"%(i+1))
data = datalist[i]
for j in range(0,8):
sheet.write(i+1,j,data[j]) #因为第0行放的是列名
book.save(savepath)
if __name__ == '__main__':#当程序执行时
main() #调用函数
print('爬取完毕')
结果展示:
26补充SQLite
如果数据库名称下边有红色波浪线,在点击右侧栏database——“+”——datasource——sqlite——弹窗中下面有黄色感叹号点击更新即可
SQLite 存储类
每个存储在 SQLite 数据库中的值都具有以下存储类之一:
具体看:https://www.runoob.com/sqlite/sqlite-data-types.html
如数据类型
INT
INTEGER
TINYINT
SMALLINT
MEDIUMINT
BIGINT
UNSIGNED BIG INT
INT2
INT8
对应的亲和类型是INTEGER
CHARACTER(20)
VARCHAR(255)
VARYING CHARACTER(255)
NCHAR(55)
NATIVE CHARACTER(70)
NVARCHAR(100)
TEXT
CLOB
对应的亲和类型是TEXT
BLOB
no datatype specified
对应NONE
REAL
DOUBLE
DOUBLE PRECISION
FLOAT
对应REAL
NUMERIC
DECIMAL(10,5)
BOOLEAN
DATE
DATETIME
对应NUMERIC
test.db刷新后 main下面有张company的表
company----右键SQL Scripts----Source Editor—可以直接定位到编写表的代码
1连接数据库
2建表
3插入数据
4查询数据
import sqlite3
# #1连接数据库
# conn=sqlite3.connect('test.db')#打开火创建数据库文件 conn就是一个对象
# print('open database successfully')
# #2创建数据表
#
# c=conn.cursor()#获取游标
# sql='''
# create table company
# (id int primary key not null,
# name text not null,
# age int not null,
# address char(50),
# salary real);
#
# '''
# c.execute(sql)#执行sql语句
# conn.commit()#提交数据库操作
# conn.close()#关闭数据库连接
# print('create table successfully')
#3插入数据
conn=sqlite3.connect('test.db')#打开火创建数据库文件 conn就是一个对象
print('open database successfully')
c=conn.cursor()#获取游标
sql1='''
insert into company(id,name,age,address,salary)
values(1,'张三',32,'成都',8000);
'''
sql2='''
insert into company(id,name,age,address,salary)
values(2,'李四',40,'北京',12000);
'''
c.execute(sql1)#执行sql语句
c.execute(sql2)#执行sql语句
conn.commit()#提交数据库操作
conn.close()#关闭数据库连接
print('insert data successfully')
#4查询数据
conn=sqlite3.connect('test.db')#打开火创建数据库文件 conn就是一个对象
print('open database successfully')
c=conn.cursor()#获取游标
sql='select id,name,age,address,salary from company'
cursor=c.execute(sql)#要有一个接收查询结果的游标 #这是一个set类型
for row in cursor:
print('id=',row[0])
print('name=',row[1])
print('address=', row[2])
print('salary=', row[3],'\n')
conn.close()#关闭数据库连接
print('search data successfully')
27.保存数据到SQLite
报错:sqlite3.OperationalError: near “value”: syntax error
解决:insert into table(xxx,xxx,xxx)
values(xxx,xxx,xxx)#记得是values不是value
def saveData2DB(datalist,dbpath):
init_db(dbpath)#保存数据之前先创建数据库
conn=sqlite3.connect(dbpath)
cur=conn.cursor()
#要先把datalist的内容组成sql语句 datalist是二维数据每条数据都是一个电影信息,所以要为每条电影信息生成一个sql语句
#把每行电影信息组成一个sql语句
for data in datalist:
for index in range(len(data)):#拿出data的每一列其实是有八列,每拼好一条语句就执行sql
if index == 4 or index ==5:#第4和第5是评分和人数 是numeric类型的不加“ ”,因为还有id编码
continue
data[index]='"'+data[index]+'"'#因为插入数据库,数据要变成文本,所以在数据前后加上双引号
sql='''
insert into movie250(
info_link,pic_link,cname,ename,score,rated,instroduction,info
)
values(%s)'''%','.join(data)#%s占位,表示得到的每个字符用逗号分割开来
#print(sql)
cur.execute(sql)
conn.commit()
cur.close()
conn.close()
print('...')
def init_db(dbpath):#创建初始化数据库的过程
# 创建数据库
sql='''
create table movie250
(
id integer primary key autoincrement,
info_link text,
pic_link text,
cname varchar,
ename varchar,
score numeric ,
rated numeric ,
instroduction text,
info message_text
)
'''
conn=sqlite3.connect(dbpath)#创建数据表或者打开数据表(存在打开,不存在创建)
cursor=conn.cursor()
cursor.execute(sql)
conn.commit()
conn.close()
28数据可视化
1flask入门
2echarts应用
3wordcloud应用
4项目说明
flask核心:路由转发和模板渲染
路由请求:不同的请求到底要访问哪一个处理逻辑,需要做一个比对,而这个比对由werkzeug来完成。
模板渲染:jinja2来完成
flask是web框架,我们只需要专注在请求和响应上
29补充flask(上)
static 放一些css文件
templates放一些html文件
app.run() #启动服务器 不断监听5000端口有没有用户访问,如果有用户访问,进行相应操作,相应操作就是上面的三句话
from flask import Flask
app = Flask(__name__)
#路由解析 ,通过用户访问的路径,匹配相应的函数,当用户访问的/的时候 返回的是helloworld
@app.route('/')#
def hello_world():
return '你好!'
if __name__ == '__main__':
app.run()
edit condigurations-debug✔-成功开启debug模式
from flask import Flask,render_template
app = Flask(__name__)
#app.debug=True
#路由解析 ,通过用户访问的路径,匹配相应的函数,当用户访问的/的时候 返回的是helloworld
@app.route('/')#
def hello_world():
return '你好喜喜123!'
@app.route("/index")
def hello():
return'hello'
#通过访问路径,获取用户的字符串参数
@app.route("/user/<name>")#<>表示变量
def welcome(name):#把用户访问的名字传进来
return'你好%s'%name
#通过访问路径,获取用户的整形参数 此外还有float的
@app.route("/user/<int:id>") # <int:>表示把传进去的整形当作int看
def welcome2(id): # 把用户访问的名字传进来
return '你好%d号会员' %id
#虽然welcome1和2看起来的路径一样但是因为后面的参数不同可以匹配不同的路由,这样可以实现访问字符串还是id
#路由路径不能重复,用户通过唯一路径访问特定函数
#返回给用户渲染后的网页文件
@app.route('/')#当用户访问/的时候 调用index2函数 然后执行html模板的渲染
def index2():
return render_template('index.html')#实现了把网页转给用户的过程
if __name__ == '__main__':
app.run()
#{{}}里面传递是前面视图函数的变量
#向页面传递一个变量
@app.route('/')#当用户访问/的时候 调用index2函数 然后执行html模板的渲染
def index3():
time=datetime.date.today()#普通变量
list=['小张','小王','小陈']#列表变量
task={'任务':"打扫卫生",'时间':"3hours"}#字典变量
return render_template('index.html',var=time,list=list,task=task)#把参数传到页面
#表单提交
@app.route('/test/register')
def register():
return render_template('test/register.html')#test文件夹下的register
#接收表单提交的路由,需要指定methods为post,否则默认为get请求 会报错”方法不被允许“
@app.route('/result',methods=['POST','GET'])
def result():
#把form这个表单形成一个字典传给result,key就是html中的name,value就是输入的内容
if request.method=='POST':
result = request.form
return render_template('test/result.html',result=result)#在页面上拿到表单的所有内容
return
if __name__ == '__main__':
app.run()
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--post 当搜索和登录的时候用post表单加密,url_for可以动态生成'http://127.0.0.1:5000/result'-->
<form action="{{ url_for('result') }}",method="post">
<p>姓名:<input type="text" name="姓名"></p>
<p>年龄:<input type="text" name="年龄"></p>
<p>性别:<input type="text" name="性别"></p>
<p>地址:<input type="text" name="地址"></p>
<p><input type="submit",value="提交"></p>
</form>
</body>
</html>
31首页自制
在index.html中在assets ctrl-c+ctrl-r 在前面加上satatic/asset replace all
这样就是显示正常的在网页预览的页面,而不是只有文字
正常:
只有文字:
在页面源代码找不到对应图标代码的位置时候,可以复制文字在pycharm 对应的html中的找,ctrl-f,复制查找
32列表页制作
对html文件进行修改
如果想更换图标可以在iconfont中进行查找
给文本加超链接
<td><a href="{{ movie[1] }}" target="_blank">{{ movie[3] }}</a></td><!--在文字里面加超链接 [1]就是我们提取出的超链接 target=blank就是可以重新打开一个新的网页 原网页不会被覆盖>
@app.route('/movie')
def movie():
datalist=[]#存取当前的data 否则不能data里面的值保存下来,直接关闭游标和数据库数据就没对应的data指针
con=sqlite3.connect('movie.db')
cur=con.cursor()
sql='select*from movie250'#查询所有信息放在datalist里面
data=cur.execute(sql)
for item in data:
datalist.append(item)
cur.close()
con.close()
return render_template('movie.html',movies=datalist)
修改movie.html 因为要把数据库数据传到页面上所以要进行for循环
<table class="table table-striped">
<tr>
<td>排名</td>
<td>电影中文名称</td>
<td>电影外文名称</td>
<td>评分</td>
<td>评价人数</td>
<td>一句话概述</td>
<td>其他信息</td>
</tr>
{% for movie in movies %}
<tr>
<td>{{ movie[0] }}</td>
<td><a href="{{ movie[1] }}" target="_blank">{{ movie[3] }}</a></td><!--在文字里面加超链接 [1]就是我们提取出的超链接 target=blank就是可以重新打开一个新的网页 原网页不会被覆盖-->
<td>{{ movie[4] }}</td>
<td>{{ movie[5] }}</td>
<td>{{ movie[6] }}</td>
<td>{{ movie[7] }}</td>
<td>{{ movie[8] }}</td>
</tr>
{% endfor %}
</table>
33补充echarts
官网下载echarts.min.js
五分钟快速入门:
https://echarts.apache.org/zh/tutorial.html#5%20%E5%88%86%E9%92%9F%E4%B8%8A%E6%89%8B%20ECharts
ECharts 基础概念概览:https://echarts.apache.org/zh/tutorial.html#5%20分钟上手%20ECharts
三部分:1初始化找到要显示的位置,在这个位置生成一个对象。2对象显示的效果由配置决定,设置参数,对option进行配置3配置设置好了就显示出来
34echarts应用
引入文件:<script src="static/assets/js/echarts.min.js"></script>
记得要修改路径,前面添加"static/assets/js
可以试着执行sql语句,movie250-右键SQL Scipts-Source Editor-execute
@app.route('/score')
def score():
score=[]#评分
num=[]#每个评分对应的电影数量
con = sqlite3.connect('movie.db')
cur = con.cursor()
sql = 'select score,count(score) from movie250 group by score' # 查询所有信息放在datalist里面
data = cur.execute(sql)
for item in data:
score.append(item[0])#可以直接不加”“做x轴
#如果要变str模式 score.append(str(item[0])) 后面改成{score|tojson}
num.append(item[1])
cur.close()
con.close()
return render_template('score.html',score=score,num=num)
score.append(item[0])
,没有进行str和后面tojson的转化,横坐标是int类型,8.3,8.4,8.5
如果变str模式 score.append(str(item[0])) 后面改成{score|tojson}
显示的x轴是字符串类型,’‘8.3",“8.4”,"8.5’’
score.HTML
<!-- ======= Counts Section ======= -->
<section class="counts section-bg">
<div class="container">
<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div id="main" style="width: 100%;height:300px;"></div>
</div>
</section><!-- End Counts Section -->
<script type="text/javascript">
var dom = document.getElementById("main");
var myChart = echarts.init(dom);
var app = {};
var option;
option = {
xAxis: {
type: 'category',
data:{{ score|tojson }},
<!--['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun','xixi'] 对比一个原格式 tojson是变成str模式-->
},
yAxis: {
type: 'value'
},
series: [{
data:
{{ num }},
<!--[120, 200, 150, 80, 70, 110, 130,1471]-->
type: 'bar'
}]
};
if (option && typeof option === 'object') {
myChart.setOption(option);
}
</script>
</div>
</section><!-- End Our Team Section -->
<!-- ======= Footer ======= -->
<footer id="footer">
<div class="container">
<div class="copyright">
© Copyright <strong><span>Mamba</span></strong>. All Rights Reserved
</div>
<div class="credits">
<!-- All the links in the footer should remain intact. -->
<!-- You can delete the links only if you purchased the pro version. -->
<!-- Licensing information: https://bootstrapmade.com/license/ -->
<!-- Purchase the pro version with working PHP/AJAX contact form: https://bootstrapmade.com/mamba-one-page-bootstrap-template-free/ -->
Designed by <a href="https://bootstrapmade.com/">BootstrapMade</a>
</div>
</div>
</footer><!-- End Footer -->
<a href="#" class="back-to-top"><i class="icofont-simple-up"></i></a>
<!-- Vendor JS Files -->
<script src="static/assets/vendor/jquery/jquery.min.js"></script>
<script src="static/assets/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="static/assets/vendor/jquery.easing/jquery.easing.min.js"></script>
<script src="static/assets/vendor/php-email-form/validate.js"></script>
<script src="static/assets/vendor/jquery-sticky/jquery.sticky.js"></script>
<script src="static/assets/vendor/venobox/venobox.min.js"></script>
<script src="static/assets/vendor/waypoints/jquery.waypoints.min.js"></script>
<script src="static/assets/vendor/counterup/counterup.min.js"></script>
<script src="static/assets/vendor/isotope-layout/isotope.pkgd.min.js"></script>
<script src="static/assets/vendor/aos/aos.js"></script>
<!-- Template Main JS File -->
<script src="static/assets/js/main.js"></script>
</body>
</html>
35wordcloud应用
背景图片必须是纯白色
# -*- codeing = utf-8 -*-
# @Time :2021/3/7 20:56
# @Author:sueong
# @File:test.py
# @Software:PyCharm
#准备词云所需的文字(词)
import jieba #分词
from matplotlib import pyplot as plt#绘图 数据可视化
from wordcloud import WordCloud#词云
from PIL import Image#图片处理
import numpy as np#矩阵运算
import sqlite3#数据库
con=sqlite3.connect('movie.db')
cur=con.cursor()
sql='select instroduction from movie250'
data=cur.execute(sql)
print(data)
text=''
for item in data:
text=text+item[0]
print(text)
#分词
cut=jieba.cut(text)#<generator object Tokenizer.cut at 0x00000242B532F5E8> 对象
string=' '.join(cut)#把对象变字符串 且以空格分开
print(len(string))#5559
print((string))
img=Image.open(r'.\static\assets\img\tree.jpg')#打开遮罩图片
img_array=np.array(img)#将图片转换为数组
wc = WordCloud(
background_color='white',
mask=img_array,
font_path="msyh.ttc" #字体所在位置:C:\Windows\Fonts
)#封装对象
wc.generate_from_text(string)#每次给的是一个词 不停返回当前的对象 从文本string生成词云
#绘制图片
fig=plt.figure(1)
plt.imshow(wc)
plt.axis('off')#是否是坐标轴
#plt.show()
plt.savefig(r'.\static\assets\img\word.jpg',dpi=500)
地址:F:\pythonProject1\testcloud
F:\pythonProject1\douban_flask
F:\pythonProject1\douban
源码:
36项目完结
37项目要点补充
1爬取数据
2数据保存
3搭建框架
4制作图标