python3学习---连接数据库,多线程,json,爬虫入门

# 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("下载完成")

爬虫部分引用了其他人的博客
引用博客
讲的非常详细 实操满满 !

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值