Python笔记(从入门到爬取数据写入excel与数据库)

这篇博客详细介绍了Python的基础语法,包括字符格式化输出、输入输出、循环、类型转换等。此外,还讲解了列表、元组、字典等数据结构的使用,以及文件操作、异常处理。接着,博主分享了Python的错误异常处理、正则表达式、BeautifulSoup库进行网页解析的方法。最后,讨论了如何利用urllib进行网络请求,包括GET和POST,以及文件I/O操作,如写入Excel和SQLite数据库。此外,还涉及到了词云生成和爬取豆瓣电影数据的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python笔记(从入门到爬取数据写入excel与数据库)

内容有点多,慢慢看,会有收获的!!

字符格式化输出

%的用法
age = 18
name = '小帅锅'
# % 占位符 %d 数字占位符 %s 字符串占位
print("我的年龄是: %d"%age)  
print('my name is %s'%name)
print('my name is %s , my age is %d'%(name,age))

输出 :  我的年龄是: 18
   	    my name is 小帅锅
	    my name is 小帅锅 , my age is 18
sep(分割)、end 的用法
# 字符分割
print('www','baidu','com')
print('www','baidu','com',sep='.')
# end 用法
print('hello',end='') # end 什么都不写 表示不换行
print('word',end='\t') # 空格
print('python',end='\n') # 换行
print('end') # 不加end 默认换行
input 输入用法
# input 输出: (不论输入int or str  输出type 都为 str 字符串)
# 若输出用%d 则报 TypeError 错
注: TypeError: %d format: a number is required, not str
        
pwd = input('请输入密码:')
print('您刚才输入的密码是: %s'%pwd)

请输入密码:aaa
您刚才输入的密码是: aaa

# 类型转换
a = int('123')
print(type(a)) #输出 a 的类型
b = a + 100
print(b)

<class 'int'>
223

num = int(input('输入数字:'))
print('输入了一个数字: %d'%num)

输入数字:123
输入了一个数字: 123

random 随机数

# 引入第三方库
import random
# 随记生成 0-2 之间的随机数
num = random.randint(0,2)
print(num)   # 0 / 1  /  2

循环

for循环
# 基本循环
for i in range(5):
    print(i,end='\t')
输出: 0 1 2 3 4

# 从0开始 到10结束(不包含10) 步进值为2(每次加2)
for i in range(0,10,2): 
    print(i,end='\t')
输出: 0 2 4 6 8

# 遍历列表(相当于数组)
numList = ['12','32','32','44']
for i in range(len(numList)):
    print(i,'-->',numList[i])
    # python 拼接用 , Java 是 +
输出: 
    0 --> 12
    1 --> 32
    2 --> 32
    3 --> 44	
while循环
# while 循环
count = 0
while count < 5:
    print('当前是第%d几次执行循环'%(count+1))
    count += 1 # python 不能写成 count++ 
输出 : 
    当前是第1几次执行循环
    当前是第2几次执行循环
    当前是第3几次执行循环
    当前是第4几次执行循环
    当前是第5几次执行循环
# while 也可以结合 else 进行使用 Java不可以
count = 10
while count < 5 :
    print(count)
    count += 1
else:
    print('大于等于5')
输出: 大于等于5

break 跳出循环

continue 跳出当前循环

pass 占位语句 不作任何事情

字符串、列表、元组、字典

字符串
# 可以写入多条字符串
strs = """this a gog
this is a cat
aaa"""
print(strs,end='')
输出: 
this a gog
this is a cat
aaa

strs = "chengdu"
print(strs)
print(strs[0]) # 输出第一个字母
print(strs[0:5]) # 输出前5个字母 下标从0开始
print(strs[1:7:2]) #从下标为1的位置开始 每次加2
print(strs[5:]) #输出下标为5后面的所有 不包含下标为5的位置
print(strs[:5]) #输出下标为5前面的所有 不包含下标为5的位置

输出:
chengdu
c
cheng
hnd
du
cheng

print(strs+"aaa") #字符串拼接
print("chengdu\nhello") #转义字符
print(r"hello\nchengdu") # 输出字符串全部
输出:
chengdu
hello
cheng\ndu

列表(List)
  • 列表可以完成大多数集合类的数据结构实现。列表中元素的类型可以不相同,它支持数字、字符串甚至可以包含列表(所谓嵌套)
  • 列表是写在中括号之间、用逗号分割开的元素列表
  • 列表索引值以0未开始值 -1为从末尾的开始位置
  • 列表可以使用+操作进行拼接,使用*表示重复
nameList = ["小张","小王","小李"]
print(nameList[0])
testList = [1,"aaa"]
print(type(testList[0]))
print(type(testList[1]))
输出:
小张
<class 'int'>
<class 'str'>
遍历列表
# for循环遍历
for name in nameList:
    print(name,end=" ")
输出:
小张 小王 小李 

# while循环遍历 (好处: 可以得到下标)
i = 0
while i < len(nameList):
    print(i,'-->',nameList[i])
    i += 1
输出: 
0 --> 小张
1 --> 小王
2 --> 小李
常用操作(增、删、改、查、排序)
  • append

    1> 往列表里追加数据

    nameList = ["小张","小王","小李"]
    print("------增加前,名单列表的数据-------")
    for name in nameList:
        print(name)
    strs = input("请输入添加的学生姓名:")
    nameList.append(strs)
    print("------增加后,名单列表的数据-------")
    for name in nameList:
        print(name)
        
    输出: 
    ------增加前,名单列表的数据-------
    小张
    小王
    小李
    请输入添加的学生姓名:王二
    ------增加后,名单列表的数据-------
    小张
    小王
    小李
    王二
    

    2> 讲一个列表追加到另一个列表中

    a = [1,2]
    b = [3,4]
    a.append(b) # append
    print(a)
    输出:
    [1, 2, [3, 4]]
    
    a.extend(b)  # [1, 2, 3, 4]  
    
  • insert (向指定位置插入数据)

    a = [1,2,3,4]
    
    a.insert(1,'a') # 第一个变量表示下标,第二个变量表示要插入的对象元素
    print(a)
    输出 :
    [1, 'a', 2, 3, 4]
    
删除
  • del

    a = ['a','b','c','d','e']
    print("------删除前,列表的数据-------")
    for i in a:
        print(i)
    print("------删除后,列表的数据-------")
    del a[1]
    for i in a:
        print(i)
    输出:
    ------删除前,列表的数据-------
    a
    b
    c
    d
    e
    ------删除后,列表的数据-------
    a
    c
    d
    e
    
  • pop() 弹出末尾的最后一个元素

  • remove() 直接删除指定内容的元素

    a = ['a','b','c']
    print("------删除前,列表的数据-------")
    for i in a:
        print(i)
    print("------删除后,列表的数据-------")
    a.remove("b")
    for i in a:
        print(i)
    输出:
    ------删除前,列表的数据-------
    a
    b
    c
    ------删除后,列表的数据-------
    a
    c
    
修改
a = ['a','b','c']
print("------修改前,列表的数据-------")
for i in a:
    print(i)
print("------修改后,列表的数据-------")
a[0]='R'  # 直接指定下标修改内容
for i in a:
    print(i)
  • in , not in

    strs = input("请输入要查询的元素:")
    a = ['a','b','c']
    if strs in a:
        print("查到了")
    else:
        print("没查到")
    输出:
    请输入要查询的元素:b
    查到了
    
  • index

    a = ['a','b','c','a','f']
    print(a.index("a",1,4)) # 可以查找指定下标范围的元素,并返回找到对应数据的下标 范围左闭右开 找不到会报错 需要try捕获
    输出:
    3
    # count 
    print(a.count("a")) #统计某个元素出现次数
    输出:
    2
    
元组

Python的核心数据类型 Tuple(元组)

  • tuple与list类似 不同之处在于tuple的元素不能修改,tuple写在小括号里,元素之间用逗号隔开。

  • 元组的元素不可变 但可以包含可变的对象 如list

    注意:定义一个只有一个元素的元组,必须加**逗号 ** 如 t1 = (1,)

tup1 = (1,2)
tup2 = ('a','b')
tup = tup1+tup2 # 相当于拼接
print(tup)
输出:
(1, 2, 'a', 'b')
删除
tup1 = (1,2)
print(tup1)
del tup1  # 直接删除了元组的变量 不是清空 tup1 直接不存在了

字典(dict)
  • 字典是无需的对象集合,使用键值(key-value)存储,具有极快的查找速度。
  • 键(key)必须使用不可变类型
  • 同一个字典中,键(key)必须是惟一的 值(value)可以重复
#字典的定义
info = {"name":"lyc" ,"age":18}
#字典的访问
print(info["name"])
#访问不存在的键
print(info["address"])  # 直接访问 会报错
print(info.get("adress")) # 使用get方法 没有找到对应的键 默认返回 None
输出: None
print(info.get("adress","m")) # 没找到值,可以指定一个默认值
输出: m
info = {"name":"lyc" ,"age":18}
newId = input("请输入学号:")
info["id"] = newId
print(info.get("id"))
输出:  1
del:
    
info = {"name":"lyc" ,"age":18}
del info["name"] #删除字典中的某个元素
del info #删除整个字典
print(info.get("name")) 
# 注意: 表明直接删除了这个元素 用info["name"] 这种方式访问会报错
输出: None  

clear() :  #清空
    
info = {"name":"lyc" ,"age":18}
info.clear()
print(info)
输出: {}
    
info = {"name":"lyc" ,"age":18}
info["age"] = 20
print(info["age"])
输出: 20
info = {"id":1,"name":"lyc" ,"age":18}
print(info.keys()) #获取到所有的键(列表)
print(info.values()) #获取到所有的值(列表)
print(info.items()) # 获取到所有的项(列表),每个键值对是一个元组
输出:
dict_keys(['id', 'name', 'age'])
dict_values([1, 'lyc', 18])
dict_items([('id', 1), ('name', 'lyc'), ('age', 18)])

遍历所有的键

info = {"id":1,"name":"lyc" ,"age":18}
for key in info.keys():
    print(key)
输出:
id
name
age

遍历所有的值

info = {"id":1,"name":"lyc" ,"age":18}
for value in info.values():
    print(value)
输出:
1
lyc
18

for key,value in info.items():
    print("key: %s,value: %s"%(key,value))
输出:
key: id,value: 1
key: name,value: lyc
key: age,value: 18

#通过枚举类型也可以拿到我们的下标与值
mylist = ['a','b','c','d']
for k,v in enumerate(mylist):
    print("key : %s , value : %s"%(k,v))
输出:
key : 0 , value : a
key : 1 , value : b
key : 2 , value : c
key : 3 , value : d

文件

# 打开文件
# 打开一个文件 W(写模式) 模式 若文件不存在 则新建
f = open("test.txt","w")  
f.write("hello py") # 将字符串写入文件中

# read()方法 读取指定的字符 开始时定位在文件的头部 每执行一次 向后移动指定字符数

f.read(5) #  读文件内容
f.close() # 关闭流
文件访问模式
  • r 以只读方式打开文件 文件指针会放在文件的开头 这是默认模式
  • w 打开一个文件只用于写入,如果该文件已存在则覆盖,若不存在,则新建
  • a 打开一个文件用于追加,如果文件已经存在,文件指针会放在文件结尾,也就是说 新的内容将会被写入到已有内容之后,若文件不存在,新建文件进行写入
  • rb 以二进制格式打开一个文件 用于只读, 文件指针放在文件的开头
  • wb 以二进制格式打开一个文件用于写入,若文件已经存在 则覆盖 若不存在 则新建
  • ab 以二进制格式打开一个文件用于追加 若文件已存在,文件指针会放在文件的结尾,也就是说 新的内容将会被写入到已有内容之后,若文件不存在,新建文件进行写入
  • r+ 打开一个文件用于读写 文件指针将会放在文件的开头
  • w+ 打开一个文件用于读写 如果该文件已经存在则覆盖 反之 创建新文件
常用方法
  • readlines() 全部读完 生成一个列表 每行一个字符串元素

    f = open("test.txt","r")
    content = f.readlines()
    print(content)
    f.close()
    输出:
    ['hello py\n', 'hello py\n', 'hello py\n', 'hello py\n', 'hello py\n', 'hello py\n', 'hello py']
    
    # 格式读取内容
    f = open("test.txt","r")
    content = f.readlines()
    i = 1
    for temp in content:
        print("%d:%s"%(i,temp),end="")
        i += 1
    f.close()
    输出:
    1:hello py
    2:hello py
    3:hello py
    4:hello py
    5:hello py
    6:hello py
    7:hello py
    
  • read() 读取内容 读取指定的字符 开始时定位在文件的头部 每执行一次 向后移动指定字符数

f = open("test.txt","r")
content = f.read(5)  # read()方法 读取指定的字符 开始时定位在文件的头部 每执行一次 向后移动指定字符数
print(content)
content
f.close()
输出:
hello

f = open("test.txt","r")
content = f.read(5)
print(content)
content = f.read(3)
print(content)
f.close()
输出:
hello
 py
  • readline() 一次读取一行
文件重命名
  • os 模块中的rename() 可以完成对文件的重命名操作

rename(需要修改的文件名,新的文件名)

import os
os.rename("毕业论文.txt","毕业论文-修改版.txt")
  • os 模块中的remove() 可以完成对文件的删除操作

    rename(待删除的文件名)

    import os
    os.remove("毕业论文.txt")
    
  • 其他操作

import os
# 获取当前目录
os.getcwd()
# 改变目录列表
os.chdir("../")
# 获取目录列表
os.listdir("./")
# 删除文件夹
os.rmdir("名称")

错误异常

try:
    ....
except error:
    ....
finally :
    .....

Python爬虫

urllib用法
import  urllib.request
#获取一个get请求
res = urllib.request.urlopen("http://www.baidu.com")
print(res.read().decode("utf-8")) # 对获取到的网页源码进行utf-8解码

# 获取一个post请求
# 测试网址 httpbin.org
#HTTP Error 405: METHOD NOT ALLOWED  不允许这样直接访问 需要封装一个表单信息 以form表单的形式发给服务器
import urllib.parse
data = bytes(urllib.parse.urlencode({"hello":"word"}),encoding="utf-8")
#用post方式访问别人的时候 必须得按照post的方式封装数据 通过data来传递一个参数 传递的参数需要通过bytes()字节文件封装进去 一般用在模拟用户登录的状态 若要有更多的用户名密码需要模拟的 都放进去 
res = urllib.request.urlopen("http://httpbin.org/post",data = data)
print(res.read().decode("utf-8"))

输出:
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "hello": "word"
  }, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Content-Length": "10", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Python-urllib/3.9", 
    "X-Amzn-Trace-Id": "Root=1-60c5c4ca-414cf3d51187a2734519ea80"
  }, 
  "json": null, 
  "origin": "183.42.44.244", 
  "url": "http://httpbin.org/post"
}


# 超时处理 在指定的时间内 无返回 则进行处理 进行下一步
# 假设超时时间设置为0.1 让他超时
res = urllib.request.urlopen("http://httpbin.org/get",timeout=0.1)
print(res.read().decode("utf-8"))
输出: 
error:  urllib.error.URLError: <urlopen error timed out>
# 通过try进行捕获处理
try :
    res = urllib.request.urlopen("http://httpbin.org/get",timeout=0.1)
    print(res.read().decode("utf-8"))
except urllib.error.URLError :
   print("time out!")      
输出: 
 time out!
伪装浏览器
# 伪装前
res = urllib.request.urlopen("https://movie.douban.com/top250")
print(res.status)  # 查看浏览器属性信息
print(res.headers) # 获取浏览器请求头的全部信息
print(res.getheader("Server")) # 获取具体的请求头信息   BWS/1.1 getheader()  没有s 查全部 有s
输出:
error : urllib.error.HTTPError: HTTP Error 418: 
            
# 伪装后
url = "https://movie.douban.com/top250"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36"
}
req = urllib.request.Request(url=url,headers=headers)  # 封装一个请求对象
res = urllib.request.urlopen(req) # 将封装好的请求对象传给urllib
print(res.read().decode("utf-8"))
文档解析(BeautifulSoup4)用法
# 打开一个文件 以rb的形式
# rb 以二进制格式打开一个文件 用于只读, 文件指针放在文件的开头
file = open("./baidu.html","rb") 
HtmlDocument = file.read().decode("utf-8")
# 创建一个BeautifulSoup对象 解析html 以 html.parser 的格式
bs = BeautifulSoup(html, "html.parser")

print(bs) # 整个文档

print(bs.tltle) # 拿到 HtmlDocument 内容的第一个出现的title标签及其内容
输出: <title>百度一下你就知道</title>
print(bs.a) #  拿到第一个出现的a标签及其内容

print(ba.title.string) # 获取标签下的文本内容 输出的内容不包含注释 自动解析注释
输出: 百度一下你就知道

print(bs.a.attrs) # 拿到一个标签里的所有属性
原文: <a class='mnav' href='http://news.baidu.com'>新闻</a>
输出:{'class':['mnav'],'href':'http://news.baidu.com'}

文档的遍历

print(bs.head.contents) # 返回一个列表 获取到特定标签的特定内容 head标签的内容 

print(bs.head.contents[1]) # 用列表索引来获取它的某一个元素

文档的搜索

find_all()

字符串过滤: 会查找与字符串完全匹配的内容

st = bs.find_all("a")  # 查找网页所有的a标签 返回一个列表
print(st)

# 查找出id="head"的标签及子标签内容
# 并不一定非要是id 可以说class / text ...
st_list = bs.find_all(id="head")
for item in st_list :
    print(item)
    
# limit = ?  可以限定你要查出的数据的数量
st_list = bs.find_all(class="head", limit=3)
for item in st_list :
    print(item) # 查出所有内容的前3条数据
正则表达式搜索
image-20210613212003344
方法函数

传入一个函数(方法) 根据函数要求来搜索

def name_is_exists(tag)return tag_has_attr("name")  # 包含name属性

st_list = bs.find_all(name_is_exists) 
print (st_list) # 返回所有包含name属性的标签 是个列表
# 可以遍历列表来格式化 打印输出
for item in sts_list :
    print(item)
选择器

标签 id class 都可

# 通过标签来查找
t_list = bs.select('title')
print(t_list)
# 通过类名(class)来查找
t_list = bs.select('.manv')
print(t_list)
# 通过id来查找
t_list = bs.select('#nav')
print(t_list)
# 通过标签还有它的class属性来查找特定的内容
t_list = bs.select('a[class='bri']')
print(t_list)
# 查找head标签里面的子标签来查找
t_list = bs.select('head > title')
print(t_list)

正则表达式操作

正则表达式的常用操作符号
image-20210613211259941 image-20210613211743044

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oIzeW5Tf-1624142016207)(C:\Users\edp06\AppData\Roaming\Typora\typora-user-images\image-20210613233835457.png)]

示例:

import re 

linkFind = re.compile()   # 创建正则表达式对象 表示规则

# 创建模式对象
pat = re.compile("AA") # 此处的AA 是正则表达式,用来验证其他的字符串
m = pat.search("CBA") # search字符串被检验的内容
print(m) #输出 None

m = pat.search("ABCAA") 
print(m) # 输出: <re.Match Object; span(3,5) match='AA'> 
 		# span表示出现的位置 5 左闭右开

# 没有模式对象
# 第一个参数为正则表达式,用来验证其他的字符串
# 第二个参数为被检验的字符串
m = re.search("asd","Aasd") 

# findall(arg1,arg2) 第一个参数为字符串规则(正则表达式)第二个参数为被检验的字符串对象
list = re.findall("a","Adwdabja") 
print(list) # ['a','a'] 输出类型为列表

list = re.findall("[A-Z]","AdwBabja") 
print(list) # ['A','B'] 输出类型为列表


#sub(arg1,arg2,arg3) 在第三个参数中 用参数2来替换参数1
print(re.sub('a','A','abc')) 
输出:Abc

excel表格操作

import xlwt
workBook = xlwt.Workbook(encoding="utf-8")    # 创建一张excel表
# cell_overwrite_ok=Tru  是否允许覆盖掉之前的数据
workSheet = workBook.add_sheet("sheet1",cell_overwrite_ok=Tru)   # 创建工作薄
workSheet.write(0, 0, "hello py")   # 第一个参数表示行 第二个参数表示列 第三个参数表示写入的数据
workBook.save("text.xls")  # 保存数据


# 九九乘法表
# 乘法表写入excel
import xlwt
workBoot = xlwt.Workbook(encoding="utf-8")  # 创建一张excel表
workSheet = workBoot.add_sheet("九九乘法表", cell_overwrite_ok=True)  # 创建工作薄
for i in range(0, 9):
    for j in range(0, i + 1):
        # workSheet.write(i, j, str(str(i+1) + '*' + str(j+1) + '=' + str((i+1) * (j+1))))
        workSheet.write(i, j, "%d*%d=%d" % (i+1, j+1, (i+1)*(j+1)))
workBoot.save("text.xls")

SqlLite数据库操作

import sqlite3  # 引入库

conn = sqlite3.connect("test.db")  # 打开或创建数据库文件
print("成功打开数据库")
c = conn.cursor()  # 获取游标
sql = '''
  create table stu(
  id int primary key not null,
  name text not null,
  age int not null
  );
'''       # sql语句
c.execute(sql)  # 执行sql语句
conn.commit()  # 提交数据库操作
conn.close()  # 关闭数据库连接

python库下载链接(非官方)

# 当下载一些库下载不下来的时候 可以从这里下载
# 安装时 需要和自己的python版本一致
ifd.uci.edu/~gohlke/pythonlibs/#wordcloud

词云(wordCloud)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M69VQM5G-1624142016210)(C:\Users\edp06\AppData\Roaming\Typora\typora-user-images\image-20210620002416463.png)]

# wordCloud 
# 需要引入的库
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('move.db')
cursor = con.cursor()  # 游标
# 查出要分的数据
sql = '''
select instroduction from move250
'''
data = cursor.excute(sql) # 执行sql 
text = ""
for item in data:
    text = text + item[0] # 将数据拿出来赋给text字符串
cursor.close() # 关闭游标
con.close() # 关闭连接

#jieba 分词
cut = jieba.cut(text) # 是个对象
str = ' '.join(cut) # 用空格进行拆分 分割
print(len(str)) # 打印出词汇的数量

#绘图
# 打开一张图  背景色必须为白色!
img = Image.open('图片的路径(r'.\static\assets\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(str)  # 根据文本生成新的wordloud 需要的是切好的词汇

# 绘制图片
fig = pit.figure(1)
plt.immshow(wc) # 按照 新的wordloud 的规则显示
plt.axis('off')  # 是否显示坐标轴
plt.show()  # 效果显示 显示生成的词云图片

 #输出词云图片到指定文件  dpi 清晰度
plt.savefig('要生成的目标路径(r'.\static\assets\tree.jpg', dpi=500)')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ThJoGX1S-1624142016211)(C:\Users\edp06\AppData\Roaming\Typora\typora-user-images\image-20210620010514682.png)]

Python案例

Python爬取豆瓣电影数据

爬取豆瓣电影数据 并存入excel表格与数据库

# -*-coding = utf-8 -*-
# @Time : 2021/6/13 0:50

# https://movie.douban.com/top250
"""
基本流程
获取数据
解析内容
保存数据
"""

# response headers 我们的浏览器向服务器发送的请求
import sqlite3

from bs4 import BeautifulSoup  # 网页解析 获取数据
import re  # 正则表达式 进行文字匹配
import urllib.request   # 制定url 获取网页数据
import urllib.error
import xlwt  # 进行excel操作
# import sqlite3  # 进行sqlLite数据库操作


def main():
    baseurl = "https://movie.douban.com/top250?start="
    # 1、爬取网页
    dataList = getData(baseurl)
    savePath = "豆瓣电影250.xls"
    # 3、保存数据到excel
    savaData(dataList, savePath)
    # 保存数据到数据库(sqlite)
    saveSqlPath = "move.db"
    saveDataToSQLite(dataList, saveSqlPath)

# 定义搜索正则表达式规则
# 创建正则表达式对象 表示规则
# 电影链接
linkFind = re.compile(r'<a href="(.*)?">')
# 图片
ImgSrcFind = re.compile(r'<img.*?src="(.*?)"', re.S)    # re.S 让换行符包含在字符中
# 电影名
MoveNameFind = re.compile(r'<span class="title">(.*?)</span>')
# 评分
MoveScoreFind = re.compile(r'<span class="rating_num" property="v:average">(.*?)</span>')
# 评价人数
CountPeoFind = re.compile(r'<span>(\d*)人评价</span>')
# 概况
ContentMsgFind = re.compile(r'<span class="inq">(.*?)</span>')
# 影片相关内容
BdFind = re.compile(r'<p class="">(.*?)</p>', re.S)    # re.S 让换行符包含在字符中

def getData(baseurl):
    dataList = []
    for i in range(0, 10):  # 调用页面信息的函数 10次
        url = baseurl + str(i * 25)
        # 调用解析网页方法
        html = askURL(url)  # 保存网页获取到的源码

        # 2、逐一解析数据
        bs = BeautifulSoup(html, "html.parser")   # 创建一个BeautifulSoup对象 解析html 以 html.parser 的格式
        # 通过BeautifulSoup 的选择器来查找内容
        itemList = bs.select(".item")
        for item in itemList:
            data = []   # 用来保存一部电影想要保存的全部信息
            # 将html对象转为字符串
            item = str(item)
            # 通过正则表达式 搜索电影链接
            link = re.findall(linkFind, item)[0]   # 可能查出好几个链接 只保留第一个
            data.append(link)   # 追加进列表
            # 图片链接
            img = re.findall(ImgSrcFind, item)[0]
            data.append(img)
            # 电影名
            moveName = re.findall(MoveNameFind, item)   # 片名可能只有一个中文名
            if len(moveName) == 2:
                chinaName = moveName[0]
                data.append(chinaName)  # 添加中文名
                outName = moveName[1].replace("/", "")   # 去掉无关的符号
                data.append(outName)    # 添加外国名
            else:
                data.append(moveName[0])
                data.append(" ")   # 外国名留空
            # 评分
            MoveScore = re.findall(MoveScoreFind, item)[0]
            data.append(MoveScore)
            # 评价人数
            CountPeo = re.findall(CountPeoFind, item)[0]
            data.append(CountPeo)
            # 概况信息
            ContentMsg = re.findall(ContentMsgFind, item)
            if len(ContentMsg) != 0:
                content = ContentMsg[0].replace("。", "")    # 去掉句号
                data.append(content)
            else:
                data.append(" ")
            # 相关内容
            Bd = re.findall(BdFind, item)[0]
            # sub(arg1,arg2,arg3) 在第三个参数中 用参数2来替换参数1
            Bd = re.sub('<br/>(\s+)?', " ", Bd)
            Bd = re.sub('/', " ", Bd)
            data.append(Bd.strip())  # strip() 去掉前后空格
            dataList.append(data)
    return dataList


# 得到一个指定的URL网页内容
def askURL(url):
    header = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (XHTML, like Gecko) "
                      "Chrome/91.0.4472.77 Safari/537.36 "
    }
    # 伪装浏览器请求
    request = urllib.request.Request(headers=header, url=url)
    # 接收网页信息
    html = ""
    try:
        # 发起请求
        response = urllib.request.urlopen(request)
        # 读取数据
        html = response.read().decode("utf-8")
    except urllib.error.URLError as e:
        # 打印错误信息的code
        if hasattr(e, "code"):
            print('this one-->', e.code)
        # 打印错误信息的原因
        if hasattr(e, "reason"):
            print('this two-->', e.reason)
    return html


# 保存数据
def savaData(dataList, savePath):
    # 创建工作表
    wookBook = xlwt.Workbook(encoding="utf-8")
    # 创建工作薄
    wookSheet = wookBook.add_sheet("sheet1", cell_overwrite_ok=True)
    # 写入行头( 电影链接、图片链接、电影中文名、电影外国名、评分、评论人数、概况信息、相关内容 )
    nameList = ("电影链接", "图片链接", "电影中文名", "电影外国名", "评分", "评论人数", "概况信息", "相关内容")
    # 循环行头列表 将行名写入excel
    for i in range(0, len(nameList)):
        wookSheet.write(0, i, nameList[i])
    # 循环数据列表
    for j in range(0, len(dataList)):
        # 取出一条
        data = dataList[j]
        print("第%d条数据" % (j+1))
        for n in range(0, len(nameList)):
            # 写入excel
            wookSheet.write(j+1, n, data[n])
    # 保存数据至excel表格
    wookBook.save(savePath)

def saveDataToSQLite(dataList, saveSqlPath):
    init_sqlDB(saveSqlPath)
    conn = sqlite3.connect(saveSqlPath)
    cursor = conn.cursor()
    for data in dataList:
        for index in range(len(data)):
            data[index] = '"'+data[index]+'"'
        print(data)
        sql = '''
            insert into move250(
            link_move, link_pic, c_name, e_name, score, count_peo, instroduction, info
            )values(%s) ''' % ",".join(data)
        print(sql)
        cursor.execute(sql)
        conn.commit()
    cursor.close()
    conn.close()

# 创建初始化数据库
def init_sqlDB(dbPath):
    sql = '''
     create table move250 
     (
     id integer primary key autoincrement,
     link_move text,
     link_pic text,
     c_name varchar,
     e_name varchar,
     score numeric,
     count_peo numeric,
     instroduction text,
     info text
     )
    '''  # 创建数据库表
    conn = sqlite3.connect(dbPath)
    cursor = conn.cursor()  # 创建游标
    cursor.execute(sql)  # 执行sql
    conn.commit()  # 提交sql
    cursor.close()  # 关闭游标
    conn.close()  # 关闭连接

if __name__ == "__main__":
    # 调用函数
    main()

Python生成九九乘法表写入excel表格
import xlwt
workBoot = xlwt.Workbook(encoding="utf-8")  # 创建一张excel表
workSheet = workBoot.add_sheet("九九乘法表", cell_overwrite_ok=True)  # 创建工作薄
for i in range(0, 9):
    for j in range(0, i + 1):
        # workSheet.write(i, j, str(str(i+1) + '*' + str(j+1) + '=' + str((i+1) * (j+1))))
        workSheet.write(i, j, "%d*%d=%d" % (i+1, j+1, (i+1)*(j+1)))
workBoot.save("text.xls")
)values(%s) ''' % ",".join(data)
    print(sql)
    cursor.execute(sql)
    conn.commit()
cursor.close()
conn.close()

创建初始化数据库

def init_sqlDB(dbPath):
sql = ‘’’
create table move250
(
id integer primary key autoincrement,
link_move text,
link_pic text,
c_name varchar,
e_name varchar,
score numeric,
count_peo numeric,
instroduction text,
info text
)
‘’’ # 创建数据库表
conn = sqlite3.connect(dbPath)
cursor = conn.cursor() # 创建游标
cursor.execute(sql) # 执行sql
conn.commit() # 提交sql
cursor.close() # 关闭游标
conn.close() # 关闭连接

if name == “main”:
# 调用函数
main()


#### **Python生成九九乘法表写入excel表格**

```python
import xlwt
workBoot = xlwt.Workbook(encoding="utf-8")  # 创建一张excel表
workSheet = workBoot.add_sheet("九九乘法表", cell_overwrite_ok=True)  # 创建工作薄
for i in range(0, 9):
    for j in range(0, i + 1):
        # workSheet.write(i, j, str(str(i+1) + '*' + str(j+1) + '=' + str((i+1) * (j+1))))
        workSheet.write(i, j, "%d*%d=%d" % (i+1, j+1, (i+1)*(j+1)))
workBoot.save("text.xls")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值