python数据分析笔记 Pycharm的常用快捷键 •tab:代码自动补全
•Ctrl + D 复制选定的区域或行到后面或下一行
•Ctrl + Space 基本的代码完成(类、方法、属性)
•Ctrl + Alt + Space 快速导入任意类
•Ctrl+F 搜索
•Ctrl+R 替换
•Ctrl+G 寻找
•Ctrl + Shift + Enter 语句完成
•Ctrl + P 参数信息(在方法中调用参数)
•Ctrl + Q 快速查看文档
•Ctrl + 鼠标 简介
•Alt + Insert 自动生成代码
•Ctrl + W 选中增加的代码块
•Ctrl + Shift + W 回到之前状态
•Ctrl + Shift + ]/[ 选定代码块结束、开始
•Alt + Enter 快速修正
•Ctrl + Alt + L 代码格式化
•Shift + F10 运行
•Shift + F9 调试
•Ctrl + Alt + O 自动导入
•Ctrl + Alt + I 自动缩进
•Shift + F1 外部文档
•Ctrl + F1 显示错误描述或警告信息
Pycharm最全常用快捷键总结_pycharm便捷操作-CSDN博客
迭代器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 my_list = [1 , 2 , 3 , 4 ] my_iter = iter (my_list) print (next (my_iter)) print (next (my_iter)) print (next (my_iter)) print (next (my_iter))
for循环遍历
1 2 3 4 5 6 7 8 9 10 11 list = [1 , 2 , 3 , 4 ]it = iter (list ) for x in it: print (x, end=" " )
next函数
1 2 3 4 5 6 7 8 9 10 11 import sys list = [1 , 2 , 3 , 4 ]it = iter (list ) while True : try : print (next (it)) except StopIteration: sys.exit()
生成器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 def countdown (n ): while n > 0 : yield n n -= 1 generator = countdown(5 ) print (next (generator)) print (next (generator)) print (next (generator)) for value in generator: print (value, end=" " )
匿名函数lambda 1 lambda 参数1 , 参数2 , ... : 表达式
**lambda
**:定义匿名函数的关键字。
参数 :可以有一个或多个参数,用逗号分隔。
表达式 :函数的返回值,只能是一个表达式,不能包含复杂的逻辑或多行代码。
基本用法
1 2 3 4 5 add = lambda x, y: x + y print (add(3 , 5 ))
网络协议基础 HTTP状态码 类别原因短语 1XXInformational(信息性状态码)接收的请求正在处理 2XXSuccess(成功状态码)请求正常处理完毕 3XXRedirection(重定向状态码)需要进行附加操作以完成请求 4XXClient Error(客户端错误状态码)服务器无法处理请求 5XXServerError(服务器错误状态码)服务器处理请求出错
URL(统一地址访问符) •超文本传输协议(HTTP)的统一资源定位符将从因特网获取信息的五个基本元素包括在一个简单的地址中:
•传送协议。 层级URL标记符号(为[//],固定不变) 访问资源需要的凭证信息(可省略) 服务器。(通常为域名,有时为IP地址)
•端口号。 (以数字方式表示,若为HTTP的默认值“:80”可省略) 路径。(以“/”字符区别路径中的每一个目录名称)
•查询。 (GET模式的窗体参数,以“?”字符为起点,每个参数以“&”隔开,再以“=”分开参数名称与数据,通常以UTF8的URL编码,避开字符冲突的问题)
•片段。 以“#”字符为起点
request 请求格式 requests.get/post(url,params,data,headers,timeout,verify,allow_redirects,cookies) url:要下载的目标网页的URL params:字典形式,设置uRL后面的参数,比如?id=123&name=xiaoming data:字典或者字符串,一般用于pOST方法时提交数据 headers:设置user-agent、refer等请求头 timeout:超时时间,单位是秒 verify:True/False,否进行HTTPs证书验证,默认是,需要自已设置证书地址 allow_redirects:True/False是否让requests做重定向处理,默认是 cookies:附带本地的cookies数据
get返回网页内容 1 2 3 4 import requestsx = requests.get("https://www.runoob.com" ) print (x.status_code)print (x.text)
post() 发送 POST 请求到指定 url •requests.post(url, data={key: value}, json={key: value}, args)
•url 请求 url。
•data 参数为要发送到指定 url 的字典、元组列表、字节或文件对象。
•json 参数为要发送到指定 url 的 JSON 对象。
args 为其他参数,比如 cookies、headers、verify等
1 2 3 4 5 6 import requestsx = requests.post('https://www.runoob.com/try/ajax/demo_post.php' ) print (x.text)
BeautifulSoup 创建 Beautiful Soup 对象 bs4 import BeautifulSoup 1 2 3 4 5 6 7 from bs4 import BeautifulSoup #根据HTML网页字符串创建BeautifulSoup对象 soup = BeautifulSoup( html_doc, #HTML文档字符串 'html.parser', #HTML解析器 from_encoding='utf8' #HTML文档的编码 )
访问节点信息 ·通常是通过URL来定位节点并进行访问 得到节点:<a href='1.html'>Python</a>
1 2 3 4 5 6 node.name node['href' ] node.get_text()
对象 Tag :HTML 标签加上里面包括的内容就是 TagNavigableString :获取标签内部的文字
操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from bs4 import BeautifulSoupwith open ("./test.html" ) as fin: html_doc=fin.read() soup=BeautifulSoup(html_doc,"html.parser" ) div_node=soup.find("div" ,id ="content" ) print (div_node)print ("#" *30 )links=div_node.find_all("a" ) for link in links: print (link.name,link["href" ],link.get_textO) img=div_node.find("img" )
正则表达式 正则表达式(Regular Expression,简称 regex 或 regexp )是一种用于匹配和处理文本的强大工具。它通过定义特定的模式,可以快速搜索、替换或提取字符串中的内容。正则表达式在文本处理、数据验证、日志分析等场景中非常常用。
1. 普通字符 普通字符(如字母、数字)会直接匹配自身。
示例:
正则表达式 hello
可以匹配字符串 "hello"
。
2. 元字符 元字符是正则表达式中具有特殊含义的字符。常见的元字符包括:
元字符
描述
.
匹配任意单个字符(除了换行符 \n
)。
^
匹配字符串的开头。
$
匹配字符串的结尾。
*
匹配前面的字符 0 次或多次。
+
匹配前面的字符 1 次或多次。
?
匹配前面的字符 0 次或 1 次。
\d
匹配数字(等价于 [0-9]
)。
\D
匹配非数字字符。
\w
匹配字母、数字或下划线(等价于 [a-zA-Z0-9_]
)。
\W
匹配非字母、数字或下划线的字符。
\s
匹配空白字符(包括空格、制表符、换行符等)。
\S
匹配非空白字符。
[]
匹配括号内的任意一个字符。例如 [abc]
匹配 a
、b
或 c
。
`
`
()
分组,将多个字符作为一个整体进行处理。
3. 量词 量词用于指定字符的匹配次数。
量词
描述
{n}
匹配前面的字符恰好 n 次。
{n,}
匹配前面的字符至少 n 次。
{n,m}
匹配前面的字符 n 到 m 次。
4. 转义字符 如果需要匹配元字符本身,可以使用反斜杠 \
进行转义。
示例 1. 匹配邮箱地址
解释:
[\w\.-]+
:匹配用户名部分(字母、数字、点、下划线、横线)。
@
:匹配邮箱中的 @
符号。
[\w\.-]+
:匹配域名部分。
\.\w+
:匹配顶级域名(如 .com
、.cn
)。
2. 匹配手机号码
解释:
1
:手机号码以 1 开头。
[3-9]
:第二位是 3 到 9 之间的数字。
\d{9}
:后面跟着 9 位数字。
3. 匹配 URL 1 https?://[\w\.-]+\.[a-zA-Z]+
解释:
https?
:匹配 http
或 https
。
://
:匹配 ://
。
[\w\.-]+
:匹配域名部分。
\.[a-zA-Z]+
:匹配顶级域名。
4. 匹配日期(YYYY-MM-DD)
解释:
\d{4}
:匹配 4 位年份。
-
:匹配分隔符 -
。
\d{2}
:匹配 2 位月份和日期。
Python 中的正则表达式 Python 通过 re
模块支持正则表达式。以下是常用的方法:
1. re.match()
从字符串开头匹配正则表达式。
1 2 3 4 5 6 7 8 9 10 import repattern = r"hello" text = "hello world" result = re.match (pattern, text) if result: print ("匹配成功:" , result.group()) else : print ("匹配失败" )
2. re.search()
在字符串中搜索匹配正则表达式的第一个位置。
1 2 3 4 5 6 7 8 9 10 import repattern = r"world" text = "hello world" result = re.search(pattern, text) if result: print ("匹配成功:" , result.group()) else : print ("匹配失败" )
3. re.findall()
返回所有匹配的结果列表。
re.findall(pattern, string, flags=0) patten:匹配的正则表达式 string:要匹配的字符串。 flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
flags可选值如下 re.l使匹配对大小写不敏感 re.L做本地化识别(locale-aware)匹配 re.M多行匹配,影响^和$ re.s使.匹配包括换行在内的所有字符 re.U根据Unicode字符集解析字符。这个标志影响\w,\W,\b,\B. re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
1 2 3 4 5 6 7 import repattern = r"\d+" text = "我有 3 只猫和 5 只狗" result = re.findall(pattern, text) print ("匹配结果:" , result)
爬取代码示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 from bs4 import BeautifulSoup import re import urllib.request, urllib.error import xlwt findLink = re.compile (r'<a href="(.*?)">' ) findImgSrc = re.compile (r'<img.*src="(.*?)"' , 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>' ) findInq = re.compile (r'<span class="inq">(.*)</span>' ) findBd = re.compile (r'<p class="">(.*?)</p>' , re.S) def main (): baseurl = "https://movie.douban.com/top250?start=" datalist = getData(baseurl) savepath = "豆瓣电影Top250.xls" saveData(datalist,savepath) def getData (baseurl ): datalist = [] for i in range (0 , 10 ): url = baseurl + str (i * 25 ) html = askURL(url) soup = BeautifulSoup(html, "html.parser" ) for item in soup.find_all('div' , class_="item" ): data = [] item = str (item) link = re.findall(findLink, item)[0 ] 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(' ' ) 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()) datalist.append(data) return datalist def askURL (url ): head = { "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0" } request = urllib.request.Request(url, headers=head) html = "" try : response = urllib.request.urlopen(request) html = response.read().decode("utf-8" ) except urllib.error.URLError as e: if hasattr (e, "code" ): print (e.code) if hasattr (e, "reason" ): print (e.reason) return html def saveData (datalist,savepath ): print ("save......." ) book = xlwt.Workbook(encoding="utf-8" ,style_compression=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 ): data = datalist[i] for j in range (0 ,8 ): sheet.write(i+1 ,j,data[j]) book.save(savepath) if __name__ == "__main__" : main() print ("爬取完毕!" )
URL管理器 定义两个集合放在类的初始化方法中,选择集合这个数据类型,是因为集合的天然去重性,在同一个集合中不会出现一样的数据。 未爬取的URL集合,已爬取的URL集合 用来存储没有爬取过数据的URL和已经爬取过数据的URL,为防止重复爬取同 一个URL的数据
1 2 3 def __init__ (self ): self .new_urls = set () self .old_urls = set ()
获取未爬取URL集合的大小 1 2 3 def new_url_size (self ): return len (self .new_urls)
获取已爬取URL的大小 1 2 def old_url_size (self ): return len (self .old_urls)
判断是否有未爬取的URL 1 2 def has_new_url (self ): return self .new_url_size() != 0
获取一个未爬取的URL 1 2 3 4 def get_new_url (self ): new_url = self .new_urls.pop() self .old_urls.add(new_url) return new_url
将新的URL添加到未爬取的URL集合 1 2 3 4 5 def add_new_url (self,url ): if url is None : return if url not in self .new_urls and url not in self .old_urls: self .new_urls.add(url)
添加多个URL链接到未爬取的URL集合 1 2 3 4 5 def add_new_urls (self,urls ): if urls is None or len (urls) == 0 : return for url in urls: self .add_new_url(url)
示例:爬取文字数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import requestsimport pandas as pdfrom io import StringIOurl = 'https://tianqi.2345.com/Pc/GetHistory' headers = { "Referer" : "https://tianqi.2345.com/wea_history/54511.htm" , "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0" } def crawler_table (year,month ): params = { "areaInfo[areaId]" : 54511 , "areaInfo[areaType]" : 2 , "date[year]" : year, "date[month]" : month } response = requests.get(url, params=params, headers=headers) data = response.json()['data' ] df = pd.read_html(StringIO(data))[0 ] return df df_list = [] for year in range (2011 , 2022 ): for month in range (1 , 13 ): df = crawler_table(year, month) df_list.append(df) pd.concat(df_list).to_excel('北京十年间的天气数据.xlsx' , index=False )
爬取图片 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 import osimport reimport requestsimport bs4url = "https://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&dyTabStr=MCwxMiwzLDEsMiwxMyw3LDYsNSw5&word=%E5%B0%8F%E5%A7%90%E5%A7%90%E5%9B%BE%E7%89%87" headers = { "Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" , "Referer" : "https://www.baidu.com/" , "Accept-Encoding" : "gzip, deflate, br, zstd" , "Accept-Language" : "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,sl;q=0.5" , 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36' } response = requests.get(url, headers=headers, timeout=10 ) response.encoding = "utf-8" print (response.status_code)html = response.text bs = bs4.BeautifulSoup(html, "html.parser" ) img_url_list = re.findall(r'"objURL":"(.*?)"' , html) img_path = "./图片/" if not os.path.exists(img_path): os.makedirs(img_path) count = 0 for img_url in img_url_list: try : res = requests.get(img_url, headers=headers) if res.status_code == 200 : count += 1 filename = os.path.join(img_path, f"图片{str (count)} .jpg" ) with open (filename, "wb" ) as f: f.write(res.content) print (f"成功下载第{count} 张图片" , img_url) except Exception as e: pass