# python3 连接mysql数据库
'''
先用pip在命令行窗口安装mysql-connector驱动
pip install mysql-connector --index-url https://pypi.douban.com/simple
'''
import mysql.connector
mydb=mysql.connector.connect(
#连接数据库
host='127.0.0.1',
user='root',
passwd='123.com',
database='study_test' #可以直接设置数据库名 如果不存在 会提示错误信息
)
print(mydb)
# <mysql.connector.connection.MySQLConnection object at 0x00000171F1DBF1F0>
# 获得到了mysql连接对象
# 查看数据库
mycutsor=mydb.cursor()
# mycutsor.execute("show DATABASES")
# for x in mycutsor:
# print(x)
'''
('information_schema',)
('mysql',)
('performance_schema',)
('study_test',)
('sys',)
'''
# print("============================")
# # 查看表
# mycutsor.execute("show tables")
# for x in mycutsor:
# print(x)
# print(type(x)) # <class 'tuple'> 是一个元组
# ('t_user',)
# 插入数据(单条)
# sql="insert into t_user(c_user,c_name,c_age,c_gender) values(%s,%s,%s,%s)"
# val=('zxy','小邹',18,'1')
# mycutsor.execute(sql,val)
# mydb.commit() #事务提交
# if mycutsor.rowcount>0:
# print(mycutsor.rowcount,'记录插入成功')
# else:
# print("插入失败")
# 1 记录插入成功
# 插入数据 (多条)
# sql="insert into t_user(c_user,c_name,c_age,c_gender) values(%s,%s,%s,%s)"
# val=[('xw','小王',20,'1'),
# ('xl','小李',19,'0'),
# ('xx','小徐',21,'0'),
# ('xb','小白',25,'1')]
# mycutsor.executemany(sql,val)
# mydb.commit() # 事务提交
# if mycutsor.rowcount>0:
# print(mycutsor.rowcount,'记录插入成功')
# else:
# print("插入失败")
# 4 记录插入成功
# 一般对于有自增长主键的表,有时候新增后可能用到新增的这个数据的主键id
# 这里只需要调用 mycursor.lastrowid 即可
# print("============================")
# # 查询数据
# mycutsor.execute("select * from t_user where 1=1")
# myresult=mycutsor.fetchall() #查询所有
# print(type(myresult)) # <class 'list'>
# for x in myresult:
# print(x)
'''
('xb', '小白', 25, 1)
('xl', '小李', 19, 0)
('xw', '小王', 20, 1)
('xx', '小徐', 21, 0)
('zxy', '小邹', 18, 1)
'''
# print("=====================")
# mycutsor.execute("select * from t_user where 1=1")
# myresult=mycutsor.fetchone() #查询一条
# print(type(myresult)) # <class 'tuple'>
# print(myresult) # ('xb', '小白', 25, 1)
# for x in myresult:
# print(x)
'''
xb
小白
25
1
'''
# 条件语句就在sql后面加就行了
# 但防止sql注入,可以用占位符%s来替代
# 查询zxy
print("=====================")
sql="select * from t_user where c_user=%s"
na=("zxy",)
mycutsor.execute(sql,na)
myresult=mycutsor.fetchall() #查询一条
print(type(myresult)) # <class 'list'>
print(myresult) # [('zxy', '小邹', 18, 1)]
for x in myresult:
print(x) # ('zxy', '小邹', 18, 1)
# 在我没注释掉前面代码的时候 这个条件查询的代码一直是报错的
# 因为cutsor游标对象的原因
'''
后面就是数据的更新与删除了 这里我就不详细写了
首先是sql的基础,sql语句会写这里应该就没什么问题
然后要注意的是 每次执行要获取游标对象
用游标对象执行sql
防止sql注入可以用%s来占位 (类似mybatis的 #号)
在涉及到数据改变的操作时要提交事务
'''
# pymysql 学习
# 依旧是利用pip安装pymysql
# pip3 install PyMySQL -i https://pypi.douban.com/simple
import pymysql
#打开数据库连接
db=pymysql.connect(host='127.0.0.1',user='root',password='123.com',database='study_test')
print(db)
#<pymysql.connections.Connection object at 0x0000015E197ED1F0>
# 注意 菜鸟教程上 是不需要指定参数名的 但3.9版本需要指定
# 不然会报错 __init__() takes 1 positional argument but 5 were given
#获取操作游标
# cursor=db.cursor()
#
# # 插入数据
# sql="insert into t_user(c_user,c_name,c_age,c_gender) values(%s,%s,%s,%s)"
# # val=('xx','小肖',19,1) #新增失败是因为我的xx已经存在
# val=('xq','小齐',19,1)
# try:
# cursor.execute(sql,val) #执行sql
# print("新增成功",cursor.rowcount) # 新增成功 1 小齐执行成功
# db.commit()# 提交事务
# except:
# print("新增失败",cursor.rowcount) # 新增失败 0
# db.rollback() #失败则回滚事务
# db.close() #关闭连接
# 查询数据库
#获取操作游标
cursor=db.cursor()
# sql语句
sql='select * from t_user where 1=1 '
sql=sql+' and c_age>%s '
val=('20')
try:
cursor.execute(sql,val)
res=cursor.fetchall()
print(res) # (('xb', '小白', 25, 1), ('xx', '小徐', 21, 0))
for x in res:
print(x)
'''
('xb', '小白', 25, 1)
('xx', '小徐', 21, 0)
'''
except:
print("查询出错")
db.close() #关闭连接
'''
这块操作其实和connMysql差不多 就不细致写了
下面了解一下几种错误类型
Warning 当有严重警告时触发,例如插入数据是被截断等等。必须是 StandardError 的子类。
Error 警告以外所有其他错误类。必须是 StandardError 的子类。
InterfaceError 当有数据库接口模块本身的错误(而不是数据库的错误)发生时触发。 必须是Error的子类。
DatabaseError 和数据库有关的错误发生时触发。 必须是Error的子类。
DataError 当有数据处理时的错误发生时触发,例如:除零错误,数据超范围等等。 必须是DatabaseError的子类。
OperationalError 指非用户控制的,而是操作数据库时发生的错误。例如:连接意外断开、 数据库名未找到、事务处理失败、内存分配错误等等操作数据库是发生的错误。 必须是DatabaseError的子类。
IntegrityError 完整性相关的错误,例如外键检查失败等。必须是DatabaseError子类。
InternalError 数据库的内部错误,例如游标(cursor)失效了、事务同步失败等等。 必须是DatabaseError子类。
ProgrammingError 程序错误,例如数据表(table)没找到或已存在、SQL语句语法错误、 参数数量错误等等。必须是DatabaseError的子类。
NotSupportedError 不支持错误,指使用了数据库不支持的函数或API等。例如在连接对象上 使用.rollback()函数,然而数据库并不支持事务或者事务已关闭。 必须是DatabaseError的子类。
'''
# python3 多线程
'''
线程的一些基本概念,在java中我已经接触很多了 这里直接学习python中线程相关的知识
'''
# 两个常用模块 _thread ,threading(推荐使用)
#引入线程模块
import _thread
# def game(threadName):
# count=0
# while count<100:
# count=count+1
# print(f"{threadName}正在打游戏")
#创建一个线程
# try:
# _thread.start_new_thread(game,('thread1',))
# print("线程创建成功")
# except:
# print("线程创建错误")
#
# count=0
# while count<100:
# count = count + 1
# print("学习")
#
# while 1:
# pass
'''
输出结果 可以看到学习和打游戏输出
说明有两个线程 while 1 的作用是保证程序不关闭
'''
'''
Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。
_thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。
threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
run(): 用以表示线程活动的方法。
start():启动线程活动。
join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名
'''
#可以看出threading模块和java中还是有点相似的
# 使用threading模块线程
import threading
#
# # 创建类 继承threading中的Thread类
# class myThread(threading.Thread):
# #重写init 和run方法
# def __init__(self,threadID,name):
# #调用父类的init
# threading.Thread.__init__(self)
# self.threadID = threadID
# self.name = name
# def run(self):
# print(f"线程开始:{self.name}")
# #要执行多线程的代码
# printInfo(self.name)
# print(f"退出线程:{self.name}")
#
# # 定义一个方法
# def printInfo(threadName):
# count=0
# while count<30:
# count=count+1
# print(f'{threadName}输出了')
# print()
#
# # 创建新线程
# thread1=myThread(1,'thread1')
# thread2=myThread(2,'thread2')
#
# #开启线程
# thread1.start()
# thread2.start()
# thread1.join()
# thread2.join()
# print ("退出主线程")
# 线程同步
'''
使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,
lock=threading.Lock
rlock=threading.RLock
lock.acquire() # 获取锁
lock.release() # 释放锁
rlock.acquire()
rlock.release()
'''
'''
线程这一块儿还是有点不好理解 主要在于python和java对于线程的创建方式以及一些方法,虽然存在相似,但是还是有区别的;
这个到时候找找视频再深入学习一下吧。
'''
# json 模块
'''
json模块也是非常常用的,在做javaweb时,json经常做前后端交互的数据传输
'''
'''
json String -》 json.loads() -》 python object
python string -》 json.dumps() -》 json object
'''
'''
python -> json
dict -> object
list,tuple -> array
str -> string
int ,float -> number
True,False -> true,false
None -> null
'''
# 引入json模块
import json
#创建字典对象
data_dict={
'id':1,
'name':'小邹',
'url':'www.baidu.com'
}
# 转为json
json_str=json.dumps(data_dict,ensure_ascii=False)
print(f"python 数据为:{data_dict}")
print(f'json 数据为:{json_str}')
'''
python 数据为:{'id': 1, 'name': '小邹', 'url': 'www.baidu.com'}
json 数据为:{"id": 1, "name": "\u5c0f\u90b9", "url": "www.baidu.com"}
'''
#解决一下中文乱码的问题
'''
原因 :json解析中文会默认使用的ascii编码.
增加参数 ensure_ascii=False
修改的输出结果:
python 数据为:{'id': 1, 'name': '小邹', 'url': 'www.baidu.com'}
json 数据为:{"id": 1, "name": "小邹", "url": "www.baidu.com"}
'''
#将json转python对象
data2=json.loads(json_str)
print(type(data2)) # <class 'dict'>
print(data2) # {'id': 1, 'name': '小邹', 'url': 'www.baidu.com'}
'''
如果处理的不是python对象 而是文件
可以使用json.dump和json.load来编码和解码json数据
'''
# 开始正式进入爬虫了
'''
这边是我要主要学习的地方 我会根据网络博客来进行学习
'''
# 简单实例
'''
两种方式进行爬取
urllib.request #urllib库是python内置的,无需我们额外安装,只要安装了Python就可以使用这个库。
requests #requests库是第三方库,需要我们自己安装。
'''
# 实现使用pip安装requests
# pip3 install requests -i https://pypi.douban.com/simple
'''
了解一下requests库的基础方法
requests.request() 构造一个请求,支撑以下各种方法的基础方法
requests.get() 获取HTML网页的主要方式,对应于HTTP的get请求
requests.head() 获取html网页头信息的方法,对应于HTTP的HEAD
requests.post() 向HTML网页提交post请求的方法,对应于HTTP的Post
requests.put() 向HTML网页提交PUT请求的方法,对应于HTTP的PUT
requests.patch() 向HTML网页提交局部修改请求,对应于HTTP的PATCH
requests.delete() 想HTML页面提交删除请求,对应HTTP的delete
相当于基于restful风格的方式
'''
#简答小测试
import requests
if __name__=='__main__':
target='http://gitbook.cn/' # 目标网站
req=requests.get(url=target)
print(req.text)
'''
requests.get()方法必须设置的一个参数就是url,因为我们得告诉GET请求,我们的目标是谁,我们要获取谁的信息。
'''
# 可以看到控制台输出了这个网页的全部信息
# 这里爬取某小说网站的小说
#引入requests模块
import requests
# if __name__=='__main__':
# # 目标网站
# target='https://www.bqkan.com/1_1094/5403177.html'
# req=requests.get(url=target)
# print(req.text)
# 得到了网站内容 但是我们要的是html的小说内容 而不是html代码文件
'''
爬虫的第一步,获取整个网页的html信息,已经ok了
第二步,我们就开始解析这个html信息,得到我们想要的内容
'''
# 这边我们使用Beautiful Soup来进行提取
# 第一步 安装Beautiful Soup
#pip3 install beautifulsoup4 -i https://pypi.douban.com/simple
# 第二步 引入bs模块
from bs4 import BeautifulSoup
#定位想要获取内容的位置和相关div标签
# <div id="content", class="showtxt"> 我们想要的正文内容在这个div中
#找到位置之后 我们就可以开始爬取了
# if __name__=='__main__':
# # 目标网站
# target = 'https://www.bqkan.com/1_1094/5403177.html'
# req=requests.get(url=target)
# html=req.text
# bf=BeautifulSoup(html,"html.parser")
# texts=bf.find_all('div',class_='showtxt')
# print(texts)
'''
现在我们会发现,我们要的这个div中的内容都出来了
但是 里面还包含一些其他标签 什么br 空格等
所以我们要继续改进
'''
# if __name__=='__main__':
# # 目标网站
# target = 'https://www.bqkan.com/1_1094/5403177.html'
# req=requests.get(url=target)
# html=req.text
# bf=BeautifulSoup(html,"html.parser")
# texts=bf.find_all('div',class_='showtxt')
# print(texts[0].text.replace('\xa0'*8,'\n\n'))
'''
find_all匹配的返回的结果是一个列表。提取匹配结果后,使用text属性,提取文本内容,滤除br标签。
随后使用replace方法,剔除空格,替换为回车进行分段。
在html中是用来表示空格的。replace(’\xa0’*8,’\n\n’)就是去掉下图的八个空格符号,并用回车代替
'''
# 这之后输出的结果就是我们想要的结果了
#这时候我们已经得到了小说一章的内容了 那么我们如果要想下载整本小说,就得得到每个章节的链接
'''
分析html页面
因为我原来做javaweb时也要写前端,所以有一定的前端基础 所有这块我觉得目前还是没有问题
用f12可以的定位出小说目录都被包裹在一个<div class="listmain">的div中
然后就是无序列表 dl->dd->a->a标签中是每章的url
'''
# if __name__=='__main__':
# # 目标网站
# target = 'https://www.bqkan.com/1_1094/'
# req=requests.get(url=target)
# req.encoding='gbk'
# html=req.text #不加次代码中文会乱码
# bf=BeautifulSoup(html,"html.parser")
# texts=bf.find_all('div',class_='listmain')
# print(texts[0])
'''
<div class="listmain">
<dl>
<dt>《一念永恒》最新章节列表</dt>
<dd><a href="/1_1094/22744709.html">《三寸人间》上架啦,已40万字,可以开宰啦~~</a></dd>
<dd><a href="/1_1094/22744708.html">新书《三寸人间》发布!!!求收藏!!</a></dd>
<dd><a href="/1_1094/17967679.html">第1314章 你的选择(终)</a></dd>
.......
这是这次执行的结果
'''
# 接下来我们要提取每一章的url
if __name__=='__main__':
# 目标网站
service='https://www.bqkan.com'
target = 'https://www.bqkan.com/1_1094/'
req=requests.get(url=target)
req.encoding='gbk'
html=req.text #不加次代码中文会乱码
bf=BeautifulSoup(html,"html.parser")
texts=bf.find_all('div',class_='listmain')
# 我们现在把这个texts作为一个html内容 再做处理
a_bf=BeautifulSoup(str(texts[0]),"html.parser")
#找a标签
a=a_bf.find_all('a')
# print(a) #输出看看是个里面是个什么东西
'''
[<a href="/1_1094/22744709.html">《三寸人间》上架啦,已40万字,可以开宰啦~~</a>,...
'''
#得到href标签里的内容
for each in a:
# print(each) #看看这个each里有啥
# # <a href="/1_1094/22744709.html">《三寸人间》上架啦,已40万字,可以开宰啦~~</a>
# #马上就成功了
# print(each.string) # 《三寸人间》上架啦,已40万字,可以开宰啦~~ string就是a标签之间的内容
# print(each.get('href')) # /1_1094/22744709.html 得到内容了
# 但是我们发现这个url 没有前缀啊 所以得拼接
print(each.string,service+each.get('href'))
'''
第1313章 青灯古庙伴一生 https://www.bqkan.com/1_1094/17967303.html
第1314章 你的选择(终) https://www.bqkan.com/1_1094/17967679.html
新书《三寸人间》发布!!!求收藏!! https://www.bqkan.com/1_1094/22744708.html
《三寸人间》上架啦,已40万字,可以开宰啦~~ https://www.bqkan.com/1_1094/22744709.html
完美得到结果
'''
# 练习 爬取小说 并保存
from bs4 import BeautifulSoup
import requests, sys
class downloader(object):
#初始化
def __init__(self):
self.server = 'http://www.biqukan.com/'
self.target = 'http://www.biqukan.com/1_1094/'
self.names = [] # 存放章节名
self.urls = [] # 存放章节链接
self.nums = 0 # 章节数
# 获取章节以及其url
def get_downLoad_url(self):
req=requests.get(url=self.target)
req.encoding = 'gbk'
html = req.text # 不加次代码中文会乱码
div_bf=BeautifulSoup(html,"html.parser")
div=div_bf.find_all('div',class_='listmain')
a_bf=BeautifulSoup(str(div[0]),"html.parser")
a=a_bf.find_all('a')
self.nums=len(a[20:22]) #我们只爬几章
for each in a[20:22]:
self.names.append(each.string) # 每章的标题
self.urls.append(self.server+each.get('href')) #每章的url
# 获取内容
def get_contents(self,target):
req=requests.get(url=target)
req.encoding = 'gbk'
html=req.text
bf=BeautifulSoup(html,"html.parser")
texts=bf.find_all('div', class_ = 'showtxt')
texts=texts[0].text.replace('\xa0'*8,'\n\n')
return texts
# 把内容写入文件
def writer(self,name,path,text):
write_flag=True
with open(path,'a',encoding='utf-8') as f:
f.write(name+'\n')
f.writelines(text)
f.write('\n\n')
if __name__=='__main__':
dl=downloader() #得到下载类 实例初始化
dl.get_downLoad_url(); #得到章节和url
print("开始下载!")
for i in range(dl.nums):
dl.writer(dl.names[i],r'C:\Users\zxy\Desktop\getnovel\novel.txt',dl.get_contents(dl.urls[i]))
sys.stdout.write("已下载 %.3f%%" % float(i/dl.nums)+'\r')
sys.stdout.flush()
print("下载完成")
爬虫部分引用了其他人的博客
引用博客
讲的非常详细 实操满满 !