发送请求HTTP请求类型有这么几种：GET，POST，PUT，DELETE，HEAD 以及 OPTIONS，下面分别进行介绍requestrequest是requests中的一个重要方法，所有的HTTP请求都是基于这个方法request(method, url, **kwargs)method：请求方式OPTIONS, HEAD, POST, PUT, PATCH, or DELETEurl：请求的网址**kwargs：其他可选参数params：字典或字节序列，作为参数增加到url中data：字典、字节序列或文件对象，作为Request的内容json：JSON格式的数据，作为Request的内容。headers：字典，HTTP定制请求头cookies：字典或CookieJar，Request中的cookiefiles：字典，用于传输文件auth：元组，支持HTTP的认证功能timeout：设定超时时间，单位为秒allow_redirects：布尔，重定向开关。默认Trueproxies：字典，设定代理服务器，可以增加登录认证verify：布尔，认证SSL证书的开关。默认Truestream：布尔，获取内容立即下载开关。默认Truecert：本地SSL证书路径stream：布尔，获取内容立即下载开关。默认TrueGET请求get(url, params=None, **kwargs)参数与上面的request一致，例如：r = requests.get('https://api.github.com/events')POST请求post(url, data=None, json=None, **kwargs)参数与上面的request一致，例如：r = requests.post('http://httpbin.org/post', data = {'key':'value'})PUT请求put(url, data=None, **kwargs)参数与上面的request一致，例如：r = requests.put('http://httpbin.org/put', data = {'key':'value'})DELETE请求delete(url, **kwargs)参数与上面的request一致，例如：r = requests.delete('http://httpbin.org/delete')HEAD请求head(url, **kwargs)参数与上面的request一致，例如：r = requests.head('http://httpbin.org/get')OPTIONS请求options(url, **kwargs)参数与上面的request一致，例如：r = requests.options('http://httpbin.org/get')向url传递参数url_params = {'key':'value'} # 字典传递参数，如果值为None的键不会被添加到url中 r = requests.get('your url',params = url_params) print(r.url) # 打印内容your url?key=value响应内容r.encoding #获取当前的编码 r.encoding = 'utf-8' #设置编码 r.text #以encoding解析返回内容。字符串方式的响应体，会自动根据响应头部的字符编码进行解码。 r.content #以字节形式（二进制）返回。字节方式的响应体，会自动为你解码 gzip 和 deflate 压缩。 r.request.headers #获取请求头 r.headers #以字典对象存储服务器响应头，但是这个字典比较特殊，字典键不区分大小写，若键不存在则返回None r.headers['Content-Type'] #访问headers的Content-Type内容 r.headers.get('Content-Type') #访问响应头部分内容的两种方式 r.request._cookies #获取请求的cookie r.cookies #获取响应的cookie r.cookies['example_cookie_name'] #读取cookies r.history #返回重定向信息,当然可以在请求是加上allow_redirects = false 阻止重定向 r.status_code #响应状态码 r.raw #返回原始响应体，也就是 urllib 的 response 对象，使用 r.raw.read() r.ok # 查看r.ok的布尔值便可以知道是否登陆成功 #*特殊方法*# r.json() #Requests中内置的JSON解码器，以json形式返回,前提返回的内容确保是json格式的，不然解析出错会抛异常 r.raise_for_status() #失败请求(非200响应)抛出异常定制请求头如果你想为请求添加 HTTP 头部，只要简单地传递一个 dict 给 headers 参数url = 'http://www.baidu.com/' headers = {'content-type': 'application/json', 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Mobile Safari/537.36'} r = requests.get(url, headers=headers)Cookieheader = {'user-agent': 'my-app/0.0.1''} cookie = {'key':'value'} r = requests.get/post('your url',headers=header,cookies=cookie)发送post请求通常，你想要发送一些编码为表单形式的数据——非常像一个 HTML 表单。要实现这个，只需简单地传递一个字典给 data 参数。你的数据字典在发出请求时会自动编码为表单形式：payload = {'key1': 'value1', 'key2': 'value2'} r = requests.post("http://httpbin.org/post", data=payload) print(r.text) { ... "form": { "key2": "value2", "key1": "value1" }, ... }post发送json请求：import requests import json payload = {'some': 'data'} r = requests.post('https://api.github.com/some/endpoint', data=json.dumps({'some': 'data'})) #如果传递的payload是string而不是dict，需要先调用dumps方法格式化一下 # r = requests.post(url, json=payload) #这中不用转json较方便 print(r.json())post多部分编码文件Requests 使得上传多部分编码文件变得很简单：url = 'http://httpbin.org/post' files = {'file': open('report.xls', 'rb')} r = requests.post(url, files=files)超时r = requests.get('url',timeout=1) #设置秒数超时，仅对于连接有效设置访问代理proxies = { "http": "http://10.10.1.10:3128", "https": "http://10.10.1.100:4444", } r = requests.get('http://m.ctrip.com', proxies=proxies) #如果代理需要用户名和密码，则需要这样： proxies = { "http": "http://user:pass@10.10.1.10:3128/", }会话对象会话对象让你能够跨请求保持某些参数。它也会在同一个 Session 实例发出的所有请求之间保持 cookieimport requests # 请求数据url member_url = 'https://www.yaozh.com/member/' headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36' } # session 类 可以自动保存cookies === cookiesJar session = requests.session() # 1.代码登录 login_url = 'https://www.yaozh.com/login' login_form_data = { 'username':'xiaomaoera12', 'pwd': 'lina081012', 'formhash': '54AC1EE419', 'backurl': 'https%3A%2F%2Fwww.yaozh.com%2F', } login_response = session.post(login_url,data=login_form_data,headers=headers) print(login_response.content.decode()) # 2.登录成功之后 带着 有效的cookies 访问 请求目标数据 data = session.get(member_url,headers=headers).content.decode()SSL 证书验证import requests url = 'https://www.12306.cn/mormhweb/' headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36' } # 因为hhtps 是有第三方 CA 证书认证的 # 但是 12306 虽然是https 但是 它不是 CA证书, 他是自己 颁布的证书 # 解决方法 是: 告诉 web 忽略证书 访问 response = requests.get(url=url, headers=headers, verify=False) data = response.content.deco客户端证书你也可以指定一个本地证书用作客户端证书，可以是单个文件（包含密钥和证书）或一个包含两个文件路径的元组：requests.get('https://kennethreitz.org', cert=('/path/client.cert', '/path/client.key')) <Response [200]>或者保持在会话中：s = requests.Session() s.cert = '/path/client.cert'
BeautifulSoup4简介参考： http://www.jsphp.net/python/show-24-214-1.htmlBeautifulSoup4是爬虫必学的技能。BeautifulSoup最主要的功能是从网页抓取数据，Beautiful Soup自动将输入文档转换为Unicode编码，输出文档转换为utf-8编码。BeautifulSoup支持Python标准库中的HTML解析器,还支持一些第三方的解析器，如果我们不安装它，则 Python 会使用 Python默认的解析器，lxml 解析器更加强大，速度更快，推荐使用lxml 解析器。BeautifulSoup4和 lxml 一样，Beautiful Soup 也是一个HTML/XML的解析器，主要的功能也是如何解析和提取 HTML/XML 数据。BeautifulSoup支持Python标准库中的HTML解析器,还支持一些第三方的解析器，如果我们不安装它，则 Python 会使用 Python默认的解析器，lxml 解析器更加强大，速度更快，推荐使用lxml 解析器。Beautiful Soup自动将输入文档转换为Unicode编码，输出文档转换为utf-8编码。你不需要考虑编码方式，除非文档没有指定一个编码方式，这时，Beautiful Soup就不能自动识别编码方式了。然后，你仅仅需要说明一下原始编码方式就可以了。BeautifulSoup4主要解析器，以及优缺点BeautifulSoup4简单使用假设有这样一个Html，具体内容如下： 百度一下，你就知道 新闻 hao123 地图 视频 贴吧 更多产品 from bs4 import BeautifulSoup file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html,"html.parser") # 缩进格式 print(bs.prettify()) # 格式化html结构 print(bs.title) # 获取title标签的名称 print(bs.title.name) # 获取title的name print(bs.title.string) # 获取head标签的所有内容 print(bs.head) print(bs.div) # 获取第一个div标签中的所有内容 print(bs.div["id"]) # 获取第一个div标签的id的值 print(bs.a) print(bs.find_all("a")) # 获取所有的a标签 print(bs.find(id="u1")) # 获取id="u1" for item in bs.find_all("a"): print(item.get("href")) # 获取所有的a标签，并遍历打印a标签中的href的值 for item in bs.find_all("a"): print(item.get_text()) # 获取所有的a标签，并遍历打印a标签中的内容BeautifulSoup4四大对象种类BeautifulSoup4将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:TagNavigableStringBeautifulSoupCommentTagTag通俗点讲就是HTML中的一个个标签，例如：from bs4 import BeautifulSoup file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html,"html.parser") # 获取title标签的所有内容 print(bs.title) # 获取head标签的所有内容 print(bs.head) # 获取第一个a标签的所有内容 print(bs.a) # 类型 print(type(bs.a))我们可以利用 soup 加标签名轻松地获取这些标签的内容，这些对象的类型是bs4.element.Tag。但是注意，它查找的是在所有内容中的第一个符合要求的标签。对于 Tag，它有两个重要的属性，是 name 和 attrs:from bs4 import BeautifulSoup file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html,"html.parser") # [document] #bs 对象本身比较特殊，它的 name 即为 [document] print(bs.name) # head #对于其他内部标签，输出的值便为标签本身的名称 print(bs.head.name) # 在这里，我们把 a 标签的所有属性打印输出了出来，得到的类型是一个字典。 print(bs.a.attrs) #还可以利用get方法，传入属性的名称，二者是等价的 print(bs.a['class']) # 等价 bs.a.get('class') # 可以对这些属性和内容等等进行修改 bs.a['class'] = "newClass" print(bs.a) # 还可以对这个属性进行删除 del bs.a['class'] print(bs.a)NavigableString既然我们已经得到了标签的内容，那么问题来了，我们要想获取标签内部的文字怎么办呢？很简单，用 .string 即可，例如：from bs4 import BeautifulSoup file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html,"html.parser") print(bs.title.string) print(type(bs.title.string))BeautifulSoupBeautifulSoup对象表示的是一个文档的内容。大部分时候，可以把它当作 Tag 对象，是一个特殊的 Tag，我们可以分别获取它的类型，名称，以及属性，例如：from bs4 import BeautifulSoup file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html,"html.parser") print(type(bs.name)) print(bs.name) print(bs.attrs)CommentComment 对象是一个特殊类型的 NavigableString 对象，其输出的内容不包括注释符号。from bs4 import BeautifulSoup file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html,"html.parser") print(bs.a) # 此时不能出现空格和换行符，a标签如下： # print(bs.a.string) # 新闻 print(type(bs.a.string)) # <class 'bs4.element.Comment'>遍历文档树.contents：获取Tag的所有子节点，返回一个list# tag的.content 属性可以将tag的子节点以列表的方式输出 print(bs.head.contents) # 用列表索引来获取它的某一个元素 print(bs.head.contents[1]).children：获取Tag的所有子节点，返回一个生成器for child in bs.body.children: print(child).descendants：获取Tag的所有子孙节点.strings：如果Tag包含多个字符串，即在子孙节点中有内容，可以用此获取，而后进行遍历.stripped_strings：与strings用法一致，只不过可以去除掉那些多余的空白内容.parent：获取Tag的父节点.parents：递归得到父辈元素的所有节点，返回一个生成器.previous_sibling：获取当前Tag的上一个节点，属性通常是字符串或空白，真实结果是当前标签与上一个标签之间的顿号和换行符.next_sibling：获取当前Tag的下一个节点，属性通常是字符串或空白，真是结果是当前标签与下一个标签之间的顿号与换行符.previous_siblings：获取当前Tag的上面所有的兄弟节点，返回一个生成器.next_siblings：获取当前Tag的下面所有的兄弟节点，返回一个生成器.previous_element：获取解析过程中上一个被解析的对象(字符串或tag)，可能与previous_sibling相同，但通常是不一样的.next_element：获取解析过程中下一个被解析的对象(字符串或tag)，可能与next_sibling相同，但通常是不一样的.previous_elements：返回一个生成器，可以向前访问文档的解析内容.next_elements：返回一个生成器，可以向后访问文档的解析内容.has_attr：判断Tag是否包含属性搜索文档树find_all(name, attrs, recursive, text, **kwargs)在上面的例子中我们简单介绍了find_all的使用，接下来介绍一下find_all的更多用法-过滤器。这些过滤器贯穿整个搜索API，过滤器可以被用在tag的name中，节点的属性等。name参数：字符串过滤：会查找与字符串完全匹配的内容a_list = bs.find_all("a") print(a_list)正则表达式过滤：如果传入的是正则表达式，那么BeautifulSoup4会通过search()来匹配内容from bs4 import BeautifulSoup import re file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html,"html.parser") t_list = bs.find_all(re.compile("a")) for item in t_list: print(item)列表：如果传入一个列表，BeautifulSoup4将会与列表中的任一元素匹配到的节点返回t_list = bs.find_all(["meta","link"]) for item in t_list: print(item)方法：传入一个方法，根据方法来匹配from bs4 import BeautifulSoup file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html,"html.parser") def name_is_exists(tag): return tag.has_attr("name") t_list = bs.find_all(name_is_exists) for item in t_list: print(item)kwargs参数：from bs4 import BeautifulSoup import re file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html,"html.parser") # 查询id=head的Tag t_list = bs.find_all(id="head") print(t_list) # 查询href属性包含http://news.baidu.com的Tag t_list = bs.find_all(href=re.compile("http://news.baidu.com")) print(t_list) # 查询所有包含class的Tag(注意：class在Python中属于关键字，所以加_以示区别) t_list = bs.find_all(class_=True) for item in t_list: print(item)attrs参数：并不是所有的属性都可以使用上面这种方式进行搜索，比如HTML的data-*属性：t_list = bs.find_all(data-foo="value")如果执行这段代码，将会报错。我们可以使用attrs参数，定义一个字典来搜索包含特殊属性的tag：t_list = bs.find_all(attrs={"data-foo":"value"}) for item in t_list: print(item)text参数：通过text参数可以搜索文档中的字符串内容，与name参数的可选值一样，text参数接受 字符串，正则表达式，列表from bs4 import BeautifulSoup import re file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html, "html.parser") t_list = bs.find_all(text="hao123") for item in t_list: print(item) t_list = bs.find_all(text=["hao123", "地图", "贴吧"]) for item in t_list: print(item) t_list = bs.find_all(text=re.compile("\d")) for item in t_list: print(item)当我们搜索text中的一些特殊属性时，同样也可以传入一个方法来达到我们的目的：def length_is_two(text): return text and len(text) == 2 t_list = bs.find_all(text=length_is_two) for item in t_list: print(item)limit参数：可以传入一个limit参数来限制返回的数量，当搜索出的数据量为5，而设置了limit=2时，此时只会返回前2个数据from bs4 import BeautifulSoup import re file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html, "html.parser") t_list = bs.find_all("a",limit=2) for item in t_list: print(item)find_all除了上面一些常规的写法，还可以对其进行一些简写：# 两者是相等的 # t_list = bs.find_all("a") => t_list = bs("a") t_list = bs("a") # 两者是相等的 # t_list = bs.a.find_all(text="新闻") => t_list = bs.a(text="新闻") t_list = bs.a(text="新闻")find()find()将返回符合条件的第一个Tag，有时我们只需要或一个Tag时，我们就可以用到find()方法了。当然了，也可以使用find_all()方法，传入一个limit=1，然后再取出第一个值也是可以的，不过未免繁琐。from bs4 import BeautifulSoup import re file = open('./aa.html', 'rb') html = file.read() bs = BeautifulSoup(html, "html.parser") # 返回只有一个结果的列表 t_list = bs.find_all("title",limit=1) print(t_list) # 返回唯一值 t = bs.find("title") print(t) # 如果没有找到，则返回None t = bs.find("abc") print(t)从结果可以看出find_all，尽管传入了limit=1，但是返回值仍然为一个列表，当我们只需要取一个值时，远不如find方法方便。但是如果未搜索到值时，将返回一个None在上面介绍BeautifulSoup4的时候，我们知道可以通过bs.div来获取第一个div标签，如果我们需要获取第一个div下的第一个div，我们可以这样：t = bs.div.div # 等价于 t = bs.find("div").find("div")CSS选择器BeautifulSoup支持发部分的CSS选择器，在Tag获取BeautifulSoup对象的.select()方法中传入字符串参数，即可使用CSS选择器的语法找到Tag:通过标签名查找print(bs.select('title')) print(bs.select('a'))通过类名查找print(bs.select('.mnav'))通过id查找print(bs.select('#u1'))组合查找print(bs.select('div .bri'))属性查找print(bs.select('a[class="bri"]')) print(bs.select('a[href="http://tieba.baidu.com"]'))直接子标签查找t_list = bs.select("head > title") print(t_list)兄弟节点标签查找t_list = bs.select(".mnav ~ .bri") print(t_list)获取内容t_list = bs.select("title") print(bs.select('title')[0].get_text())
FlaskFlask简介Flask作为Web框架，它的作用主要是为了开发Web应用程序。那么我们首先来了解下Web应用程序。Web应用程序 (World Wide Web)诞生最初的目的，是为了利用互联网交流工作文档。一切从客户端发起请求开始。所有Flask程序都必须创建一个程序实例。当客户端想要获取资源时，一般会通过浏览器发起HTTP请求。此时，Web服务器使用一种名为WEB服务器网关接口的WSGI（Web Server Gateway Interface）协议，把来自客户端的请求都交给Flask程序实例。Flask使用Werkzeug来做路由分发（URL请求和视图函数之间的对应关系）。根据每个URL请求，找到具体的视图函数。在Flask程序中，路由一般是通过程序实例的装饰器实现。通过调用视图函数，获取到数据后，把数据传入HTML模板文件中，模板引擎负责渲染HTTP响应数据，然后由Flask返回响应数据给浏览器，最后浏览器显示返回的结果。Flask诞生于2010年，是Armin ronacher（人名）用Python语言基于Werkzeug工具箱编写的轻量级Web开发框架。它主要面向需求简单的小应用。Flask本身相当于一个内核，其他几乎所有的功能都要用到扩展（邮件扩展Flask-Mail，用户认证FlaskLogin），都需要用第三方的扩展来实现。比如可以用Flask-extension加入ORM、窗体验证工具，文件上传、身份验证等。Flask没有默认使用的数据库，你可以选择MySQL，也可以用NoSQL。其 WSGI 工具箱采用 Werkzeug（路由模块） ，模板引擎则使用 Jinja2 。可以说Flask框架的核心就是Werkzeug和Jinja2。Python最出名的框架要数Django，此外还有Flask、Tornado等框架。虽然Flask不是最出名的框架，但是Flask应该算是最灵活的框架之一，这也是Flask受到广大开发者喜爱的原因。Flask扩展包：Flask-SQLalchemy：操作数据库；Flask-migrate：管理迁移数据库；Flask-Mail:邮件；Flask-WTF：表单；Flask-script：插入脚本；Flask-Login：认证用户状态；Flask-RESTful：开发REST API的工具；Flask-Bootstrap：集成前端Twitter Bootstrap框架；Flask-Moment：本地化日期和时间；Flask基本使用Hello World 程序from flask import Flask # Flask类接收一个参数__name__ app = Flask(__name__) # 路由解析通过用户访问的路径，匹配相应的函数 # 装饰器的作用是将路由映射到视图函数index @app.route("/") def index(): return "hello,world" # Flask应用程序实例的run方法启动WEB服务器 if __name__ == "__main__": app.run(debug=True, host="0.0.0.0",port=3000) # debug 开启调试，更改代码内容，界面相应改变； # host改成0.0.0.0让其他机器可以访问 # port=3000端口号路由传参有时我们需要将同一类URL映射到同一个视图函数处理，比如：使用同一个视图函数 来显示不同用户的个人信息。通过向规则参数添加变量部分，可以动态构建URL。此变量部分标记为。它作为关键字参数传递给与规则相关联的函数。from flask import Flask app = Flask(__name__) @app.route("/index") def index(): return "hello,world" # 通过访问路径获取用户的字符串参数 @app.route("/user/<name>") # <name>表示name参数，需要将路径中的name参数传入下面的函数中 def Wellcome(name): return "你好%s"%name # 通过访问路径获取用户的整形参数 # 路由传递的参数默认当做string处理，这里指定int，尖括号中冒号后面的内容是动态的 # 除此之外还有 float 型 @app.route("/user/<int:id>") def Wellcome1(id): return "你好%d号会员"%id # 路由的路径不能重复，用户通过唯一路径访问特定函数 if __name__ == "__main__": app.run(debug=True, host="0.0.0.0",port=3000)使用 render_template 渲染界面上面的函数中可以 return HTML语句，达到渲染界面的效果，但这样做对于不方便可以使用 render_template 。首先从 flask 中导入 render_template 。在 同级目录下建立 templates 文件夹，在这个文件夹中创建一个 HTML 程序，取名 index.html 。在 index 函数中使用 return render_template('index.html') 就可以将写入相应的 HTML 程序在界面中渲染。源代码如下：from flask import Flask,render_template app = Flask(__name__) @app.route("/") def index(): return render_template("index.html") if __name__ == "__main__": app.run(debug=True, host="0.0.0.0",port=3000)HTML程序如下： hello world 利用循环和判断语句控制 template 渲染使用 if 判断在 HTML 程序中使用 if 判断，如下所示，其意义是当传入了 title 变量就是用传入的 title 变量，否则使用默认，此处默认设置的是 Flask App 。{% if title %} {{title}} {% else %} Flask App {% endif %}当不传入参数时，网页名字就会变成 Flask App 。@app.route('/') def index(): return render_template('index.html')传入参数时，网页名字会使用传入的名字 Home@app.route('/') def index(): return render_template('index.html', title='Home')源代码如下：from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') if __name__ == "__main__": app.run(debug=True, host="0.0.0.0",port=3000) # debug 开启调试，更改代码内容，界面相应改变； # host改成0.0.0.0让其他机器可以访问 # port=3000端口号HTML 程序如下： {% if title %} {{title}} {% else %} Flask App {% endif %} hello world 使用循环循环的基本语法如下，其意义是将 data 变量中的内容放到p标签中{% for p in data %} {{p}} {% endfor %}同样的需要传入 data 变量如下所示@app.route('/') def index(): paragraph=[ 'section 1', 'section 2', 'section 3' ] return render_template('index.html',title='Home',data=paragraph)显示结果效果如下源代码如下：from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): paragraph=[ 'section 1', 'section 2', 'section 3' ] return render_template('index.html',title='Home',data=paragraph) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0",port=3000) # debug 开启调试，更改代码内容，界面相应改变； # host改成0.0.0.0让其他机器可以访问 # port=3000端口号HTML 程序如下： {% if title %} {{title}} {% else %} Flask App {% endif %} hello world {% for p in data %} {{p}} {% endfor %} 向页面传递一个变量值得注意的是，我们可以向 HTML 中传入变量。在 render_template 函数中自定义title变量，如：render_template('index.html',title=title) 。向 render_template 定义 title 变量后，需要在 HTML 中接收该变量。使用两个大括号，在两个大括号中间写入 title 如 {{title}} ，这样就实现向 HTML 传入变量。传递普通变量from flask import Flask,render_template app = Flask(__name__) @app.route("/") def index(): title = "Flak App" #普通变量 return render_template("index.html",title=title) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0",port=3000)HTML程序如下： {{title}} hello world 传递列表传递列表如何显示呢？可以用到上面讲的for循环from flask import Flask,render_template app = Flask(__name__) @app.route("/") def index(): title = "Flak App" #普通变量 name = ["小张","小赵","小王"] #列表 return render_template("index.html",title=title,name=name) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0",port=3000)HTML程序如下： {{title}} hello world 今天值班的有： {%for n in name%} {{n}} {%endfor%} 传递字典from flask import Flask,render_template app = Flask(__name__) @app.route("/") def index(): title = "Flak App" #普通变量 name = ["小张","小赵","小王"] #列表 task = {"任务":"打扫卫生","时间":"3小时"} return render_template("index.html",title=title,name=name,task=task) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0",port=3000)HTML程序如下： {{title}} hello world 今天值班的有： {%for n in name%} {{n}} {%endfor%} {% for key,value in task.items()%} {{key}} {{value}} {%endfor%} 模板的继承和引用模板继承和修改模板中有很多共用的部分，我们可以把共用的部分写在一个文件中，可简化代码。模板的继承，首先创建 base.html 写入一些内容 {% if title %} {{title}} {% else %} Flask App {% endif %} Flask App 在 index.html 中使用关键字 extends 继承模板{% extends 'base.html' %}有时会将继承的模板里面的内容进行更改，可以使用 block 语句{% block content %} parent template {% endblock %} content 为该block的名字然后在 index.html 中同样使用上面的语句，对模板中的 block 里面的内容修改，如果不修改，就是原来 block 块中的内容{% block content %} {% for p in data %} {{p}} {% endfor %} {% endblock %}源代码如下：from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): paragraph=[ 'section 1', 'section 2', 'section 3' ] return render_template('index.html',title='Home',data=paragraph) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0",port=3000) # debug 开启调试，更改代码内容，界面相应改变； # host改成0.0.0.0让其他机器可以访问 # port=3000端口号base.html 代码如下： {% if title %} {{title}} {% else %} Flask App {% endif %} Flask App {% block content %} parent template {% endblock %} index.html 代码如下：{% extends 'base.html' %} {% block content %} {% for p in data %} {{p}} {% endfor %} {% endblock %}模板的引用比如，对于导航栏，我们可以把他写在一个组件中。命名为 navbar.html ，例如我们在里面写入： Flask AppHome 然后可以再 base.html 中引用，使用如下代码{% include 'navbar.html' %}源代码如下：from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): paragraph=[ 'section 1', 'section 2', 'section 3' ] return render_template('index.html',title='Home',data=paragraph) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0",port=3000) # debug 开启调试，更改代码内容，界面相应改变； # host改成0.0.0.0让其他机器可以访问 # port=3000端口号index.html 代码如下：{% extends 'base.html' %} {% block content %} {% for p in data %} {{p}} {% endfor %} {% endblock %}base.html 代码如下： {% if title %} {{title}} {% else %} Flask App {% endif %} {% include 'navbar.html' %} {% block content %} parent template {% endblock %} navbar.html 代码如下： Flask AppHome 表单提交我们已经看到，可以在URL规则中指定http方法。触发函数接收的Form数据可以以字典对象的形式收集它并将其转发到模板以在相应的网页上呈现它。在以下示例中，'/sign' URL会呈现具有表单的网页（sign.html）。填入的数据会发布到触发 result()函数的'/result' URL。result()函数收集字典对象中的request.form中存在的表单数据，并将其发送给result.html。该模板动态呈现表单数据的HTML表格。下面给出的是应用程序的Python代码：from flask import Flask,render_template,request app = Flask(__name__) # 表单提交页面 @app.route("/sign") def sign(): return render_template("sign.html") # 表单结果显示页面 @app.route("/result",methods=["POST","GET"]) #默认为get，其他请求需要指定 def result(): if request.method=="POST": result=request.form return render_template("result.html",result=result) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0",port=3000)sign.html 代码： title 姓名： 年龄： result.html代码如下： {% for key,value in result.items()%} {{key}} {{value}} {%endfor%} Echarts入门官方中文网址：https://echarts.apache.org/zh/index.html官方实例：https://echarts.apache.org/examples/zh/index.html官方教程：https://echarts.apache.org/zh/tutorial.html引入Echarts 设置显示区域 初始化Echarts指定配置项和数据设置配置项显示图表完整代码： ECharts WordCloudWordCloud示例程序# 引入必要的库 import jieba #分中文词 import numpy as np #矩阵运算 import sqlite3 #数据库 from matplotlib import pyplot as plt #绘图数据可视化 from wordcloud import WordCloud #词云 from PIL import Image #图片处理 # 准备词云所需的词 con=sqlite3.connect("movies.db") cur=con.cursor() sql="select instroduction from movies250" data =cur.execute(sql) text="" for item in data: text=text+item[0] # print(type(item)) cur.close() con.close() # 分词 cut =jieba.cut(text) string =' '.join(cut) # 此处' '双引号中间有空格 print(len(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='/mnt/c/Windows/Fonts/msyhl.ttc') #使用WSL子系统需要指定完整的字体路径 # 若是有中文的话，必须添加中文字体，不然会出现方框，不出现汉字 wc.generate_from_text(string) # 绘制图片 fig=plt.figure(1) #新建一个名叫 Figure1的画图窗口 plt.imshow(wc) #显示图片，同时也显示其格式 plt.axis('off') #是否显示坐标轴 plt.savefig(r"./static/assets/img/word.jpg",dpi=400) #保存合成图片，dpi是设定分辨率，默认为400WordCloud配置WordCloud个参数的含义：font_path : string #字体路径，需要展现什么字体就把该字体路径+后缀名写上，如：font_path = '黑体.ttf'width : int (default=400) #输出的画布宽度，默认为400像素height : int (default=200) #输出的画布高度，默认为200像素prefer_horizontal : float (default=0.90) #词语水平方向排版出现的频率，默认 0.9 （所以词语垂直方向排版出现频率为 0.1 ）mask : nd-array or None (default=None) #如果参数为空，则使用二维遮罩绘制词云。如果mask 非空，设置的宽高值将被忽略，遮罩形状被 mask 取代。除全白（#FFFFFF）的部分将不会绘制，其余部分会用于绘制词云。如：bg_pic = imread('读取一张图片.png')，背景图片的画布一定要设置为白色（#FFFFFF），然后显示的形状为不是白色的其他颜色。可以用ps工具将自己要显示的形状复制到一个纯白色的画布上再保存，就ok了。scale : float (default=1) #按照比例进行放大画布，如设置为1.5，则长和宽都是原来画布的1.5倍min_font_size : int (default=4) #显示的最小的字体大小font_step : int (default=1) #字体步长，如果步长大于1，会加快运算但是可能导致结果出现较大的误差max_words : number (default=200) #要显示的词的最大个数stopwords : set of strings or None #设置需要屏蔽的词，如果为空，则使用内置的STOPWORDSbackground_color : color value (default=”black”) #背景颜色，如background_color='white',背景颜色为白色max_font_size : int or None (default=None) #显示的最大的字体大小mode : string (default=”RGB”) #当参数为“RGBA”并且background_color不为空时，背景为透明relative_scaling : float (default=.5) #词频和字体大小的关联性color_func : callable, default=None #生成新颜色的函数，如果为空，则使用 self.color_funcregexp : string or None (optional) #使用正则表达式分隔输入的文本collocations : bool, default=True #是否包括两个词的搭配colormap : string or matplotlib colormap, default=”viridis” #给每个单词随机分配颜色，若指定color_func，则忽略该方法random_state : int or None #为每个单词返回一个PIL颜色fit_words(frequencies) #根据词频生成词云generate(text) #根据文本生成词云generate_from_frequencies(frequencies[, ...]) #根据词频生成词云generate_from_text(text) #根据文本生成词云process_text(text) #将长文本分词并去除屏蔽词（此处指英语，中文分词还是需要自己用别的库先行实现，使用上面的 fit_words(frequencies) ）recolor([random_state, color_func, colormap]) #对现有输出重新着色。重新上色会比重新生成整个词云快很多to_array() #转化为 numpy arrayto_file(filename) #输出到文件豆瓣Top250项目可视化代码以及资料Github仓库：https://github.com/imgyh/DouBan_Top250
准备工作该笔记围绕豆瓣TOP250页面进行学习，爬取豆瓣TOP250影片信息。网址为 https://movie.douban.com/top250?start=25 其中 ?start=25 表示显示第25个以后的25个影片信息，如果不加该参数，则从第一个开始显示。我们需要安装相应的第三方模块，如下from bs4 import BeautifulSoup #网页解析获取数据 import re #正则表达式进行文字匹配 import urllib.request , urllib.error , requests #网页请求 import xlwt #进行Excel操作 import sqlite3 #进行sqlite数据库操作项目流程# 主函数 def main(): baseurl = "https://movie.douban.com/top250?start=" # 1.爬取网页 GetData(baseurl) # 3.保存数据 savepath = "./top250.xls" SaveData(savepath) def GetData(baseurl): datalist=[] # 2.边爬取边解析数据 return datalist def SaveData(savepath): pass if __name__ == "__main__": main()urllib库介绍基本的请求 是python内置的一个http请求库，不需要额外的安装。只需要关注请求的链接，参数，提供了强大的 解析。urllb.request 请求模块urllib.error 异常处理模块urllib.parse 解析模块参考： https://www.cnblogs.com/qikeyishu/p/10748497.html# get请求 import urllib.request , urllib.error response=urllib.request.urlopen("http://www.baidu.com") print(response.read().decode("utf-8")) #对读到的响应转码成utf-8 print(response.status) # 获取状态码 print(response.getheaders()) #获取所有响应头信息 print(response.getheader("Bdqid")) #获取某个响应头信息 # post请求 import urllib.request , urllib.error import urllib.parse data = bytes(urllib.parse.urlencode({"hello":"world"}),encoding="utf-8") #生成测试数据 res = urllib.request.urlopen("http://httpbin.org/post",data=data) print(res.read().decode("utf-8")) # 超时处理 import urllib.request , urllib.error try: response=urllib.request.urlopen("http://www.baidu.com",timeout=0.01) # 设置超时时间，超过0.01s没返回就报错 print(response.read().decode("utf-8")) except urllib.error.URLError as result: print("Time Out!") # 封装请求头访问 import urllib.request , urllib.error import urllib.parse url="http://httpbin.org/post" data = bytes(urllib.parse.urlencode({"hello":"world"}),encoding="utf-8") #生成测试数据 headers={ "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36" } req = urllib.request.Request(url=url,data=data,headers=headers,method="POST") #封装请求对象,由于urlopen无法传参数，声明一个Request对象 res = urllib.request.urlopen(req) print(res.read().decode("utf-8"))数据解析BeautifulSoupBeautifulSoup使用详解参见：BeautifulSoup详解正则表达式正则表达式常用操作符操作符说明实例.表示任何单字符 [ ]字符集对单个字符给出取值范围[abc]表示a,b,c [a-z]表示a-z的字符1非字符集，对单个字符给出排除范围2表示非a或b或c的单个字符*前面一个字符0次或无限次扩展abc*表示ab,abc,abcc等+前面一个字符1次或无限次扩展abc*表示abc,abcc等?前面一个字符0次或1次扩展abc?表示ab,abc 左右表达式任意一个{m}扩展前一个字符m次ab{2}c表示abbc{m,n}扩展前一个字符m至n次(包含n)ab{1,2}c表示abc,abbc^匹配字符串开头^abc表示abc且在一个字符串开头$匹配字符串结尾abc$表示abc且在一个字符串结尾( )分组标记(abc)表示abc\d数字,邓嘉怡[0-9] \w单词字符，等价于[a-zA-Z0-9_] Re库主要功能函数函数功能re.search()在一个字符串中搜索匹配正则表达式的第一个位置，返回match对象re.match()在一个字符串的开始位置起匹配正则表达式，返回match对象re.findall()搜索字符串，以列表形式返回全部匹配到的子串re.sub()在一个字符串中替换所有配正则表达式的子串，返回替换后的字符串re.split()将一个字符串按照正则表达式匹配结果进行分割，返回列表类型re.finditer()搜索字符串，返回一个结果的迭代类型，每个迭代元素是个mat对象控制匹配的模式正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。 多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志：修饰符描述re.l使匹配对大小写不敏感re.L做本地化识别匹配re.M多行匹配影响^和$re.S使.匹配包括换行在内的所有字符re.U根据Unicode字符集解析字符，影响\b,\B\w,\Wre.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解Re模块下的函数compile(pattern)：创建模式对象import re pat=re.compile("A") #m=pat.search("CBA") m=pat.search("ABC") #等价于 re.search( A , CBA ) print(m) #<re.Match object; span=(2, 3), match='A'> 表示匹配到了 m=pat.search("CBD") print(m) #None 表示没匹配到search(pattern,string)：在字符串中寻找模式import re m = re.search("asd" , "ASDasd" ) print(m) # <_sre.SRE_Match object at 0xb72cd6e8> #匹配到了，返回MatchObject（True） m = re.search("asd" , "ASDASD" ) print(m) #没有匹配到，返回None（False）match(pattern,string)：在字符串开始处匹配模式# 等价于 pat=re.compile( "a" ) print(pat.match( "Aasd" )) #输出None print(pat.match("aASD" )) #输出 <_sre.SRE_Match object at 0xb72cd6e8> # 上面的函数返回都可以在if条件语句中进行判断： if pat.search("asd"): print ("OK") #OK #找到返回 if re.search("a","ASD" ): print ("OK") #没有找到split(pattern,string)：根据模式分割字符串,返回列表re.split( , , a,s,d,asd ) [ a , s , d , asd ] #返回列表 pat = re.compile( , ) pat.split( a,s,d,asd ) [ a , s , d , asd ] #返回列表 re.split( [, ]+ , a , s ,d ,,,,,asd ) #正则匹配：[, ]+，后面说明 [ a , s , d , asd ] re.split( [, ]+ , a , s ,d ,,,,,asd ,maxsplit=2) # maxsplit 多分割次数 [ a , s , d ,,,,,asd ] pat = re.compile( [, ]+ ) #正则匹配：[, ]+，后面说明 pat.split( a , s ,d ,,,,,asd ,maxsplit=2) # maxsplit 多分割次数 [ a , s , d ,,,,,asd ]ﬁndall(pattern,string)：列表形式返回匹配项import re print(re.findall( "a" , "ASDaDFGAa" )) #[ a , a ] #列表形式返回匹配到的字符串 pat = re.compile( "a" ) print(pat.findall( "ASDaDFGAa" )) #[ a , a ] #列表形式返回匹配到的字符串 pat = re.compile( "[A-Z]+" ) #正则匹配：[A-Z]+ print(pat.findall( "ASDcDFGAa" )) #[ ASD , DFGA ] #找到匹配到的字符串 pat = re.compile( [A-Z] ) pat.findall( ASDcDFGAa ) #正则匹配：[A-Z]+ #[ A , S , D , D , F , G , A ] #找到匹配到的字符串 pat = re.compile( [A-Za-z] ) #正则匹配：[A-Za-z]+ 匹配所有单词 pat.findall( ASDcDFGAa ) [ A , S , D , c , D , F , G , A , a ]sub(pat,repl,string) ：用repl替换 pat匹配项 (留的是中间的，因为中间在中心)re.sub( a , A , abcasd ) #找到a用A替换 AbcAsd解析部分代码from bs4 import BeautifulSoup #网页解析获取数据 import re #正则表达式进行文字匹配 import urllib.request , urllib.error , requests #网页请求 import xlwt #进行Excel操作 import sqlite3 #进行sqlite数据库操作 # 主函数 def main(): baseurl = "https://movie.douban.com/top250?start=" # 1.爬取网页 GetData(baseurl) # 3.保存数据 savepath = "./豆瓣TOP250.xls" SaveData(savepath) #详情链接 findlink=re.compile(r'') #创建正则表达式对象，表示规则 #影片图片 findsrc=re.compile(r'<img.*src="(.*?)"',re.S) #re.S让换行符包含在.匹配符其中 #影片名字 findtitle=re.compile(r'(.*?)') #影片评分 findrating=re.compile(r'(.*?)') #影片评价人数 findjudge=re.compile(r'(\d*?)人评价') #影片概况 findinq=re.compile(r'(.*?)') #影片相关内容 findbd=re.compile(r' (.*?) ',re.S) def GetData(baseurl): datalist=[] for i in range(0,10): url = baseurl + str(i*25) # 调用获取页面信息函数10次 html =AskURL(url) # 2.边爬取边解析数据 soup = BeautifulSoup(html,"html.parser") for item in soup.find_all('div',class_="item"): #查找符合要求的字符串形成列表， data = [] #保存一部影片所有信息 item=str(item) #影片详情页链接 link=re.findall(findlink,item)[0] #使用re库查找指定字符串 data.append(link) #添加链接 #影片图片 imgsrc=re.findall(findsrc,item)[0] data.append(imgsrc) #添加图片 #影片名字 titles=re.findall(findtitle,item) #片名可能只有中文名没有外文名 if (len(titles)==2): data.append(titles[0]) #添加中文名 data.append(titles[1].replace("/","")) #添加外文名 else: data.append(titles[0]) data.append("") #留空 #影片评分 rating=re.findall(findrating,item)[0] data.append(rating) #添加评分 #影片评价人数 judgenum=re.findall(findjudge,item)[0] data.append(judgenum) #添加评分 #影片概况 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) bd=re.sub("/","",bd) #去掉 / data.append(bd.strip()) #去掉空格，并添加进data datalist.append(data) print(datalist) return datalist #保存数据 def SaveData(savepath): pass #得到一个指定url的内容 def AskURL(url): headers={ #模拟浏览器头部信息，向豆瓣发送请求 "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36" } request = urllib.request.Request(url=url,headers=headers) 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"): print(e.reason) return html if __name__ == "__main__": main()数据保存保存数据到Excel参考: https://www.cnblogs.com/caesar-id/p/11802440.html使用xlwt保存数据到Excel的小demo：import xlwt workbook=xlwt.Workbook(encoding="utf-8") #创建workbook对象 worksheet=workbook.add_sheet("sheet1") #创建工作表取名sheet1 worksheet.write(0,0,"hello") #在sheet1中的第一行第一列写入hello workbook.save("student.xls") #保存数据表取名为student.xls保存数据到Excel代码from bs4 import BeautifulSoup #网页解析获取数据 import re #正则表达式进行文字匹配 import urllib.request , urllib.error , requests #网页请求 import xlwt #进行Excel操作 import sqlite3 #进行sqlite数据库操作 # 主函数 def main(): baseurl = "https://movie.douban.com/top250?start=" # 1.爬取网页 datalist=GetData(baseurl) # 3.保存数据 savepath = "./豆瓣TOP250.xls" SaveData(datalist,savepath) #详情链接 findlink=re.compile(r'') #创建正则表达式对象，表示规则 #影片图片 findsrc=re.compile(r'<img.*src="(.*?)"',re.S) #re.S让换行符包含在.匹配符其中 #影片名字 findtitle=re.compile(r'(.*?)') #影片评分 findrating=re.compile(r'(.*?)') #影片评价人数 findjudge=re.compile(r'(\d*?)人评价') #影片概况 findinq=re.compile(r'(.*?)') #影片相关内容 findbd=re.compile(r' (.*?) ',re.S) def GetData(baseurl): datalist=[] for i in range(0,10): url = baseurl + str(i*25) # 调用获取页面信息函数10次 html =AskURL(url) # 2.边爬取边解析数据 soup = BeautifulSoup(html,"html.parser") for item in soup.find_all('div',class_="item"): #查找符合要求的字符串形成列表， data = [] #保存一部影片所有信息 item=str(item) #影片详情页链接 link=re.findall(findlink,item)[0] #使用re库查找指定字符串 data.append(link) #添加链接 #影片图片 imgsrc=re.findall(findsrc,item)[0] data.append(imgsrc) #添加图片 #影片名字 titles=re.findall(findtitle,item) #片名可能只有中文名没有外文名 if (len(titles)==2): data.append(titles[0]) #添加中文名 data.append(titles[1].replace("/","")) #添加外文名 else: data.append(titles[0]) data.append("") #留空 #影片评分 rating=re.findall(findrating,item)[0] data.append(rating) #添加评分 #影片评价人数 judgenum=re.findall(findjudge,item)[0] data.append(judgenum) #添加评分 #影片概况 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) bd=re.sub("/","",bd) #去掉 / data.append(bd.strip()) #去掉空格，并添加进data datalist.append(data) # print(datalist) return datalist #保存数据 def SaveData(datalist,savepath): workbook=xlwt.Workbook(encoding="utf-8") #创建workbook对象 worksheet=workbook.add_sheet("豆瓣TOP250") #创建工作表取名sheet1 col=("电影详情链接","图片链接","影片中文名","影片外文名","评分","评价数","概况","相关信息") for i in range(0,8): worksheet.write(0,i,col[i]) #添加表头 for i in range(0,250): print("第%d条"%i) data=datalist[i] for j in range(0,8): worksheet.write(i+1,j,data[j]) workbook.save(savepath) #保存数据表取名为student.xls #得到一个指定url的内容 def AskURL(url): headers={ #模拟浏览器头部信息，向豆瓣发送请求 "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36" } request = urllib.request.Request(url=url,headers=headers) 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"): print(e.reason) return html if __name__ == "__main__": main()保存数据到数据库sqlite基本使用方法建立数据库表import sqlite3 # 建表 conn=sqlite3.connect("test.db") # 打开或创建数据库 c=conn.cursor() #获取游标 sql =''' create table commpany (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() #提交数据库操作 c.close() #关闭游标 conn.close() #关闭数据库插入数据import sqlite3 # 插入数据 conn=sqlite3.connect("test.db") # 打开或创建数据库 c=conn.cursor() #获取游标 sql1 =''' insert into commpany (id,name,age,address,salary) values (1,'张三',32,'成都',8000); ''' sql2 =''' insert into commpany (id,name,age,address,salary) values (2,'李四',30,'重庆',10000); ''' c.execute(sql1) #执行sql语句 c.execute(sql2) #执行sql语句 conn.commit() #提交数据库操作 c.close() #关闭游标 conn.close() #关闭数据库查询数据库import sqlite3 # 查询数据库 conn=sqlite3.connect("test.db") # 打开或创建数据库 c=conn.cursor() #获取游标 sql =''' select id,name,age,address,salary from commpany ''' cur=c.execute(sql) #执行sql语句 for row in cur: print("id = ",row[0]) print("name = ",row[1]) print("address = ",row[2]) print("salary = ",row[3],"\n") c.close() #关闭游标 conn.close() #关闭数据库保存数据到数据库代码from bs4 import BeautifulSoup #网页解析获取数据 import re #正则表达式进行文字匹配 import urllib.request , urllib.error , requests #网页请求 import xlwt #进行Excel操作 import sqlite3 #进行sqlite数据库操作 # 主函数 def main(): baseurl = "https://movie.douban.com/top250?start=" # 1.爬取网页 datalist=GetData(baseurl) # 3.保存数据到Excel # savepath = "./豆瓣TOP250.xls" # SaveData(datalist,savepath) # 4. 保存数据到数据库 dbpath="./movies.db" SaveData2DB(datalist,dbpath) #详情链接 findlink=re.compile(r'') #创建正则表达式对象，表示规则 #影片图片 findsrc=re.compile(r'<img.*src="(.*?)"',re.S) #re.S让换行符包含在.匹配符其中 #影片名字 findtitle=re.compile(r'(.*?)') #影片评分 findrating=re.compile(r'(.*?)') #影片评价人数 findjudge=re.compile(r'(\d*?)人评价') #影片概况 findinq=re.compile(r'(.*?)') #影片相关内容 findbd=re.compile(r' (.*?) ',re.S) def GetData(baseurl): datalist=[] for i in range(0,10): url = baseurl + str(i*25) # 调用获取页面信息函数10次 html =AskURL(url) # 2.边爬取边解析数据 soup = BeautifulSoup(html,"html.parser") for item in soup.find_all('div',class_="item"): #查找符合要求的字符串形成列表， data = [] #保存一部影片所有信息 item=str(item) #影片详情页链接 link=re.findall(findlink,item)[0] #使用re库查找指定字符串 data.append(link) #添加链接 #影片图片 imgsrc=re.findall(findsrc,item)[0] data.append(imgsrc) #添加图片 #影片名字 titles=re.findall(findtitle,item) #片名可能只有中文名没有外文名 if (len(titles)==2): data.append(titles[0]) #添加中文名 data.append(titles[1].replace("/","")) #添加外文名 else: data.append(titles[0]) data.append("") #留空 #影片评分 rating=re.findall(findrating,item)[0] data.append(rating) #添加评分 #影片评价人数 judgenum=re.findall(findjudge,item)[0] data.append(judgenum) #添加评分 #影片概况 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) bd=re.sub("/","",bd) #去掉 / data.append(bd.strip()) #去掉空格，并添加进data datalist.append(data) # print(datalist) return datalist #保存数据 def SaveData(datalist,savepath): workbook=xlwt.Workbook(encoding="utf-8") #创建workbook对象 worksheet=workbook.add_sheet("豆瓣TOP250") #创建工作表取名sheet1 col=("电影详情链接","图片链接","影片中文名","影片外文名","评分","评价数","概况","相关信息") for i in range(0,8): worksheet.write(0,i,col[i]) #添加表头 for i in range(0,250): # print("第%d条"%i) data=datalist[i] for j in range(0,8): worksheet.write(i+1,j,data[j]) workbook.save(savepath) #保存数据表取名为student.xls #得到一个指定url的内容 def AskURL(url): headers={ #模拟浏览器头部信息，向豆瓣发送请求 "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36" } request = urllib.request.Request(url=url,headers=headers) 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"): print(e.reason) return html def init_db(dbpath): sql=''' create table movies250 (id integer primary key autoincrement, info_link text, pic_link text, cname varchar, ename varchar, score numeric, rated numeric, instroduction text, info text) ''' conn=sqlite3.connect(dbpath) cursor=conn.cursor() #获取游标 cursor.execute(sql) #执行SQL语句：创建数据表 conn.commit() #事务提交：让操作生效 cursor.close() #关闭游标 conn.close() #关闭连接 def SaveData2DB(datalist,dbpath): init_db(dbpath) conn=sqlite3.connect(dbpath) cursor=conn.cursor() #获取游标 for data in datalist: for index in range(len(data)): if index ==4 or index==5: continue data[index]='"'+data[index]+'"' # sql语句中的字符串添加 " " sql = ''' insert into movies250(info_link,pic_link,cname,ename,score,rated,instroduction,info) values (%s) '''%",".join(data) # print(data) # print("%s"%",".join(data)) # print(sql) cursor.execute(sql) #执行SQL语句：创建数据表 conn.commit() #事务提交：让操作生效 cursor.close() #关闭游标 conn.close() #关闭连接 if __name__ == "__main__": main()豆瓣Top250项目可视化代码以及资料Github仓库：https://github.com/imgyh/DouBan_Top250 ↩abc ↩