第一天:
1. 今日知识大纲
本地文件读写
- 读纯文本文件:
- 编码解码
- 写纯文本文件
- With语句
- 读非纯文本文件
- 写非纯文本文件
- Base64编码
2. 核心代码
(1)读纯文本文件
# 相对路径 同级./ 父级../
# 绝对路径 copy相对路径文件路径
file = open('./chinese_utf8.txt', mode='r', encoding='utf-8')
(2)编码解码
编码方式和解码方式不一样
windows7和早期win10的记事本默认gbk保存
windows10和主流开发工具如pycharm,sublime都是utf-8
大多数中文网站utf-8,少部分gbk
(3)写纯文本文件
#参数mode: r读文本,w写文本,a追加信息,适合日志文件
file = open('./3test.txt', mode='a' ,encoding='utf-8')
file.write('hello world 你好,世界')
# 如果想换行 在‘一行’字符串表达‘换行’的概念,用‘转义’字符
#file.write('hello world \n你好,世界')
file.close()
(4)with语句
# 文件操作和其他某些操作,共性 开始前准备,主要逻辑,收尾工作
# with语句把 开始前准备和收尾工作 抽离自动完成,程序员把主要精力放在逻辑上
with open('./chinese_utf8.txt', mode='r', encoding='utf-8') as f:
content = f.read()
print(content)
(5)读非文本文件
与with语句相比,重点在于mode模式的不同
#读图片二进制
# mode: r+b b表示二进制模式 删除encoding参数
with open('./testimage.jpg', mode='r+b') as f:
print(f.read())
读是‘r+b’
(6)写非文本文件
写是‘w+b’
(7)base64编码
# 场景:1.字符串方式传播图片。 2.简单加密 3.服务器兼容性
# base64编码作用的是字节
# ‘中’ 00000001 00000001
# base64 00000000 , 0001 0000, 00000001 把真实信息一个字节取36位前面补0,得到几个新的字节,比原始信息大三分之一。
# base64之后每个字节 2的6次方64种可能,对应最简单a-z A-Z -+ 0-9
# 'aF-'
# 文本/图片 编码 -> 二进制 -> base64 改变后的二进制 -> ASCII解码成基本字符
import base64
str1 = '337845818'
content_b64 = base64.b64encode(str1.encode(encoding='utf-8'))
print(content_b64)
#b'MzM3ODQ1ODE4' 本应看到 b'16进制' 只不过是pycharm自动转换了
content_64 = content_b64.decode(encoding='ascii')
print('我的绿色软件是:', content_64)
# 图片
with open('./testimage.jpg',mode='rb') as f:
content_bytes = f.read()
content_b64_bytes = base64.b64encode(content_bytes)
content_b64_str = content_b64_bytes.decode(encoding='ascii')
print(content_b64_str)
(8)base64解码
import base64
# 文本/图片 编码 -> 二进制 -> base64 改变后的二进制 -> ASCII解码成基本字符 逆转过来
str1 = 'T3JpZHp1cnU='
str2 = 'MTM3MjUxMDc5NjQ='
b64_bytes = str1.encode(encoding='ascii')
print(b64_bytes)
raw_bytes = base64.b64decode(b64_bytes)
print(raw_bytes)
raw_str = raw_bytes.decode(encoding='utf-8')
print(raw_str)
----------------------------------------------------------------------------------------------------------------------------------------------------------------
第二天:
- 今日知识大纲
- 图解http
- Pip包管理
- Requests包应用
- Html解析-正则表达式
- Html解析-bs库
- Html解析-xpath
- 核心代码
(3)import requests
baidu_index_url = 'https://www.baidu.com'
baidu_search_url = 'https://www.baidu.com/s'
headers = {
#'cookies': '', #跟公共参数、会话用户有关
#'referer'" '', # 从哪个页面来
# 浏览器标识,容易伪造
'User-Agent':’Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1'
}
params = {
'wd':'天气',
'ie':'utf-8'
}
response = requests.get(url=baidu_search_url,params=params)
status_code = response.status_code
if status_code == 200:
#网页数据 bytes
content = response.content
#网页数据str。一般直接取text属性 但少数情况解码错误乱码
text = response.text
text = content.decode('utf-8') #很少用
print(text)
url = response.url
headers = response.headers
(4)正则表达式
#4中已经用requests模拟请求,拿到源代码,str字符串,里面是HTML格式
#需要解析
#字符串自带的find方法功能有限
html = '<html><body><h1>标题</h1></body></html>'
start_index = html.find('<h1>')
end_index = html.find('</h1>')
print(html[start_index:end_index])
#解析方式一:正则regex,专门针对字符串的语法
import re
text1 = 'javapythonasdwfdxafwfdaf'
pattern1 = re.compile(r'python')
matcher1 = re.search(pattern1,text1)
print(matcher1[0])
text2 = '<h1> hello world</h1>'
pattern2 = re.compile(r'<h1>.+</h1>')
matcher2 = re.search(pattern2,text2)
print(matcher2[0])
(5)bs4
#网页html本身是树状层次结构,按层次去找
#python3适合用beautifulsoup4
from bs4 import BeautifulSoup # 坑:代码包名字和包元信息不一样
html = """
<html>
<body>
<a id='ccc' href='https://www.baidu,com'>百度一下</a>
<a></a>
</body>
</html>
"""
bs = BeautifulSoup(html,'html.parser')
print(bs.a)
print(bs.find_all('a'))
(6)xpath
from lxml import etree
html = “...”
#把长字符串转化为html文档树
dom = etree.HTML(html)
print(dom)
# 全文匹配,匹配不到返回[],匹配到返回列表[element,elemrnt]
#语法:/表示下一层 //忽略任意层父级目录
#/body/ul/li/a
print(dom.xpath('//a'))
print(dom.xpath('//ul/li/a'))
#取html元素里的属性
#/@href取元素属性值
print(dom.xpath('//a/@href'))
#取元素内容
# /text()
print(dom.xpath('.//a/text()'))
#属性过滤[@id="second_a"]
print(dom.xpath('.//a[@id="second_a"]/text()'))
第三天:
- 今日知识大纲
- 煎蛋网爬虫
- 网易新闻爬虫
- Os库
- 天堂图片网爬虫
- 天堂图片网封装
- 核心代码
- 煎蛋网爬虫(爬取文本)
#煎蛋网爬虫
import requests
from lxml import etree
url = 'http://jandan.net/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36'
}
resp = requests.get(url=url,headers=headers)
#print(resp.status_code)
# 403 直接请求 响应码403 有资源但是禁止你访问 加上user-agent
# 304 重定向
if resp.status_code == 200:
html = resp.text
#print(html)
#小技巧:网页想要分析的地方,右键检查,自动定位
#小技巧:开发者工具elements,ctrl+f打开搜索框,在里面尝试xpath表达式
dom = etree.HTML(html)
xpath_pattern = '//div[@class="post f list-post"]/div[@class="indexs"]/h2/a/text()'
titles = dom.xpath(xpath_pattern)
#print('titles',titles)
for i in titles:
print(i)
- 天堂图片网(爬取图片)
# 天堂网爬虫
import os
import requests
from lxml import etree
# home_url = 'https://www.ivsky.com/'
# catalog_url = ''
album_url = 'https://www.ivsky.com/tupian/lugui_v62472/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36'
}
# 请求网集页
resp = requests.get(album_url)
status_code = resp.status_code
#print(status_code)
album_html = resp.text
#print(album_html)
#获取一个图集下所有缩略图片的url地址
album_dom = etree.HTML(album_html)
title_pattern = '//h1/text()'
img_pattern = '//ul[@class="pli"]/li/div/a/img/@src'
album_title = album_dom.xpath(title_pattern)[0]
album_title = album_title.strip()# 图集名
img_src_list = album_dom.xpath(img_pattern)
#print(album_title) # 输出图集名称
#print(len(img_src_list),img_src_list) #输出图片url
# 用图集名创建文件夹
if not os.path.exists('./'+album_title): #' 体型庞大的陆龟照片
os.mkdir('./'+album_title)
# 循环图片地址列表,请求每一张图片
for i,img_src in enumerate(img_src_list):
# 拼完整图片url
img_src = 'https:'+img_src # url切片
print(img_src)
resp = requests.get(img_src,headers=headers)
#print(resp.status_code)
img_content_bytes = resp.content
# 图片二进制信息写入本地
img_path = os.path.join(os.path.dirname(__file__),album_title,f'{i+1}.jpg')
print(img_path)
with open(img_path,mode='wb') as f:
f.write(img_content_bytes)
print(f'图片{i+1}写入成功,保存到了{img_path}')
第四天:
- 今日学习大纲
- 动态网页和静态网页
# 区分:如果网页的doc界面的html和elements的一样就是静态网页
# 在network中的js xhr中分析
- Json格式
- 评论请求寻找分析
# 找js xhr请求评论数据
# 不关心对方js怎么写的和渲染的网页。只要找到http请求,用python来模拟
# 寻找技巧:
# 1. 开发者工具network,过滤xhr和js的请求
# 2. 找post类型的http请求
# 3. 找比较像的名字 comment api get_info get_list
# 4. 响应的是纯数据,不是HTML信息
# 5. 尝试在网页中触发异步js请求,在开发者工具中观察变化
# 6. network工具获取焦点,ctrl+f打开隐藏的搜索框,在所有请求,请求头,响应全文搜索关键字。
- 请求天气接口
- 请求京东评论接口
- 核心代码
- json格式
import json
# json 字符串 -> python内置数据结构
xiaoming_dict = json.loads(xiaoming_json_str)
# json.load(本地文件.json)
# PYTHON内置数据结构 -> json字符串
students = [
{'name':'ming','age':13,'gender':'m'},
{'name':'hong','age':12,'gender':'wm'}
]
students_json = json.dumps(students)
print(type(students_json),students_json)
- 请求京东评论接口
import json
import requests
base_url = 'https://club.jd.com/comment/productPageComments.action'
# 本次请求头只用伪造user-agent即可,但是前端时间测试需要cookie字段
headers = {
#'Cookie' :'__jdu=1610951435695866394438',
#'Referer': 'https://item.jd.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36'
}
# 从请求头下面的query parama复制下来再调整,使用编辑器模式,alt+shift+鼠标拖动(多光标)
params = {
#'callback': 'fetchJSON_comment98', #
'productId': 100009077475, #商品id
'score': 0,
'sortType': 5,
'page': 1, #第几页
'pageSize': 10, #一页的个数
'isShadowSku': 0,
'rid': 0,
'fold': 1
}
resp = requests.get(base_url,headers=headers,params=params)
status_code = resp.status_code
comment_json = resp.text
#print(comment_json)
# 京东评论接口返回jsonp格式,涉及跨域问题 需将jsonp转化为json
# 方法1:python字符串方法删除固定长度无用字符串
# 方法2:从网上找从jsonp过滤json正则
comment_obj = json.loads(comment_json)
#print(comment_obj)
comments = comment_obj['comments']
for c in comments:
#print(c)
cid = c['id']
content = c['content']
creation_time = c['creationTime']
images = c['images']
product_color = c['productColor']
product_size = c['productSize']
print('-'*100)
print(cid,content)
(5)注意:请求接口时,要找出对应的json文件对比
第五天:
- 今日学习大纲
- sqlite数据库
- 京东爬虫数据库版
- jieba分词
- 停止词
- 核心代码
京东爬虫数据库版
import json
import sqlite3
import time
import requests
def get_one_product_one_page_comments(pid, pageno=1):
base_url = 'https://club.jd.com/comment/productPageComments.action'
# 本次请求头只用伪造user-agent即可,但前端时间测试需要cookie字段
headers = {
# 'Cookie': '__jdu=16096534364451068756302;',
# 'Referer': 'https://item.jd.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36',
}
# tips:从开发者工具network请求头下面的query params复制下来再调整。使用编辑器列编辑模式 alt+shift+鼠标拖动。
params = {
#'callback': 'fetchJSON_comment98',
'productId': pid, # 商品id
'score': 0,
'sortType': 5,
'page': pageno, # 第n页 经测试最大99页,之后只有概括数据无详细数据。
'pageSize': 10,
'isShadowSku': 0,
'rid': 0,
'fold': 1
}
# for i in range(1, 20):
# params['page'] = i
resp = requests.get(base_url, headers=headers, params=params)
status_code = resp.status_code
comments_json = resp.text
#print(comments_json)
# 京东评论接口返回jsonp格式,涉及跨域问题。需要将先jsonp转json。
# 方法1:python字符串方法删除固定长度无用字符串;2(推荐)上网找从jsonp过滤json正则;3本例中发现修改参数可以直接返回json
comments_obj = json.loads(comments_json)
#print(comments_obj)
comments = comments_obj['comments']
return comments
def write_comment_to_db(c, cursor):
cid = c['id']
content = c['content']
creation_time = c['creationTime']
images = c.get('images', None)
product_color = c['productColor']
product_Size = c['productSize']
# 一条评论写入数据库
cursor.execute("""
insert into comments (cid, content, product_color, creation_time)
values (?, ?, ?, ?);
""", [cid, content, product_color, creation_time])
def db_init():
# 数据库初始化
connect = sqlite3.connect('./jd.db')
cursor = connect.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS comments(
id INTEGER PRIMARY KEY,
cid INTEGER,
content TEXT,
product_color TEXT,
creation_time DATETIME
);
""")
if __name__ == '__main__':
db_init()
#connect = sqlite3.connect('./jd.db')
#cursor = sqlite3.connect('./jd.db').cursor()
product_id = 100009077475
for pageno in range(1, 3):
one_page_comments = get_one_product_one_page_comments(product_id, pageno)
for c in one_page_comments:
write_comment_to_db(c, cursor)
connect.commit()
print(f'第{pageno}页数据插入完成')
time.sleep(1)
connect.close()
第六天:
-
今日学习大纲
- 估算评论情感分数
- 词云图
- 核心代码
词云图
# 常用:pillow
# coding:utf-8
import jieba
import sqlite3
from wordcloud import WordCloud
connect = sqlite3.connect('../L05数据持久化和清洗/jd.db')
cursor = connect.cursor()
cursor.execute("""select * from comments order by creation_time desc limit 1,10;""")
comments_rs = cursor.fetchall()
comments = [c[2] for c in comments_rs]
comments = ''.join(comments)
#print(comments)
words = jieba.cut(comments,cut_all=False)
comment_words = [w for w in words]
#print(comment_words)
#comment_words_str = ' '.join(comment_words)
# print(comment_words_str)
comment_words_after = []
with open('./dict/stop_words_zh.txt',mode='r',encoding='utf-8') as f:
stop_words = f.read().splitlines ()
for comment_word in comment_words:
if comment_word not in stop_words:
comment_words_after.append(comment_word)
#print(comment_words_after)
comment_words_str = ' '.join(comment_words_after)
font = './STXINWEI.TTF'
wc = WordCloud(font_path=font,
background_color='white',
width=1000,
height=800,
min_font_size=50,
).generate(comment_words_str)
wc.to_file('./2评论词云图.png')
第七天:
进行项目总结。
本文是一篇关于Python编程的实践教程,涵盖了从文件的读写、编码解码、Base64编码,到HTTP请求、正则表达式、BeautifulSoup和XPath解析,再到SQLite数据库和评论情感分析的全程学习。通过实例,读者可以深入理解Python在日常开发中的应用。
1309

被折叠的 条评论
为什么被折叠?



