xpath需要应用的场景以及优点对比
1. 解析页面模块比较:
- 正则表达式是进行内容匹配,将符合要求的内容全部获取;
- xpath()能将字符串转化为标签,它会检测字符串内容是否为标签,但是不能检
测出内容是否为真的标签;
- Beautifulsoup是Python的一个第三方库,它的作用和 xpath 作用一样,都是用来解析html数据的相比之下;xpath的速度会快一点,因为xpath底层是用c来实现的
2.三者语法不同,正则表达式使用元字符,将所有获得内容与匹配条件进行匹配,
而xpath和bs4将获取的解析后的源码进行按条件筛选,筛选出想要的标签即根据标签属性来找到指定的标签,之后对标签进行对应内容获取;
# xpath:全称XML PATH Language, 一种小型的查询语言;
# 支持的解析:
XML格式
html格式
通过元素,和属性进行导航
xpath运用的基本方法
import lxml.etree as etree
html = """
<!DOCTYPE html>
<html>
<head lang="en">
<title>xpath测试</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<div id="content">
<ul id="ul">
<li>NO.1</li>
<li>NO.2</li>
<li>NO.3</li>
</ul>
<ul id="ul2">
<li>one</li>
<li>two</li>
</ul>
</div>
<div id="url">
<a href="http:www.58.com" title="58">58</a>
<a href="http:www.csdn.net" title="CSDN">CSDN</a>
</div>
</body>
</html>
"""
# 1). 将html内容转化成xpath可以解析/匹配的格式;
selector=etree.HTML(html)
# 2). 对全文进行扫描,获取需要的信息
#需求:获取文件中div的属性id为content里边ul的属性id=ul的所有文本信息
str = selector.xpath('//div[@id="content"]/ul[@id="ul"]/li/text()')
print(str)
#返回的是一个列表
print(type(str))
# 需求: 获取文件中div的属性id为”url“里面的所有a标签的href属性
str=selector.xpath('//div[@id="url"]/a/@href')
print(str)
英文的词云生成
# 实现处理英文的词云比较简单
import re
from PIL import Image
from wordcloud import wordcloud
import numpy as np
# 1. 切割和处理英文字符,
data = []
with open('/tmp/passwd') as f:
for line in f:
result1 = re.split(r'\s|:|/', line)
# 如果item存在数据并且不是空格或者数字, 则继续进行处理;
result2 = [item for item in result1 if not re.findall(r'\s+|\d+', item) and item]
data.extend(result2)
# 2). 打开图片, 获取图片的数据信息;
imgObj = Image.open('doc/img.jpg')
img_mask = np.array(imgObj)
# print(img_mask)
#
# 3). 创建词云对象, 设置属性
wcObj = wordcloud.WordCloud(
mask=img_mask,# 数据如何填充到图片
background_color='snow',# 背景颜色
min_font_size=5,# 图片中最小的字体大小
max_font_size=50,# 图片中最小的字体大小
width=1000, # 图片宽度
height=1000, # 高
)
# 4). 生成图片;
# 词云绘制时, 默认之处理字符串类型, 怎么分隔每个单词? 必须以逗号分隔符分割
wcObj.generate(','.join(data))
wcObj.to_file('doc/wcObj.png')
中文的词云生成
import re
import jieba
from PIL import Image
from wordcloud import wordcloud
import numpy as np
def gen_wordcloud(text, filename):
# 1). 强调分割中有问题的词;
jieba.suggest_freq(('微博'), True)
jieba.suggest_freq(('热搜'), True)
# 2). 难点: 如何切割中文, jieba, lcut
result = jieba.lcut(text)
# 绘制词云
# 3). 打开图片, 获取图片的数据信息;
imgObj = Image.open('doc/img.jpg')
img_mask = np.array(imgObj)
# print(img_mask)
# 4). 创建词云对象, 设置属性
wcObj = wordcloud.WordCloud(
mask = img_mask, # 数据如何填充到图片
background_color="snow", # 背景颜色
font_path="/usr/share/fonts/wqy-zenhei/wqy-zenhei.ttc", # 如果是中文, 指定字体库(fc-list :lang=zh)
min_font_size=5, # 图片中最小的字体大小
max_font_size=50, # 图片中最小的字体大小
width=1000, # 图片宽度
height=1000, # 高
)
# 5). 生成图片;
# 词云绘制时, 默认之处理字符串类型, 怎么分隔每个单词? 必须以逗号分隔符分割
wcObj.generate(",".join(result))
wcObj.to_file(filename)
if __name__ == '__main__':
text = "马云曾公开表态称对钱没兴趣称其从来没碰过钱上了微博热搜我想成为马云"
filename = 'doc/wcObj.png'
gen_wordcloud(text, filename)
mocc课程的爬取及词云的生成
- 爬取的链接: http://www.imooc.com/course/list
- 爬取的内容: 课程链接, 课程的图片url, 课程的名称, 学习人数, 课程描述
- 爬取的内容如何存储:
- 文件(.csv, );
- mysql数据库;
- 分析爬取的信息;
- 词云
- 需下载以下导入的模块,同时词云的运用还需下载matplotlib模块
import csv
import json
import re
import jieba
import lxml.etree as etree
import requests
from PIL import Image
from wordcloud import wordcloud
import numpy as np
# 解析url地址,
def get_content(url):
try:
# 获得浏览器,并以浏览器的方式爬去网页
user_agent = 'Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0'
# ,解析url地址,获得反馈,设置头部信息
response = requests.get(url, headers={'User-Agent': user_agent})
# 如果返回的状态码不是200, 则抛出异常
response.raise_for_status()
# 判断网页的编码格式, 便于respons.text知道如何解码;
response.encoding = response.apparent_encoding
except Exception as e:
print('爬取错误')
print(e)
else:
print('爬取成功')
# 返回的是bytes类型的数据
return response.content
# 返回的是str类型的数据
# return response.text
# 分析html,获取想要的信息
def parser_content(html):
"""分析页面获取需要的信息:课程链接, 课程的图片url, 课程的名称, 学习人数, 课程描述 """
# 1). 将html内容转化成xpath可以解析/匹配的格式;
selector = etree.HTML(html)
# 2). 获取每个课程的信息:
courseDetails = selector.xpath('//div[@class="course-card-container"]')
# 保存数据
courseinfo = []
for courseDetail in courseDetails:
# 课程的名称
name = courseDetail.xpath('.//h3[@class="course-card-name"]/text()')[0]
# 学习人数
student = courseDetail.xpath('.//span/text()')[1]
# 课程的图片url
img_url = 'http:' + courseDetail.xpath('.//img[@class="course-banner lazy"]/@src')[0]
# 课程链接
url = "http://www.imooc.com" + courseDetail.xpath('.//a/@href')[0]
# 课程描述
introduction = courseDetail.xpath(".//p[@class='course-card-desc']/text()")[0]
# 将每个课程的信息以元组的形式存储到列表中
courseinfo.append((name, student, introduction, img_url, url))
return courseinfo
def save_csv(courseinfo):
"""将获取的课程信息保存为csv格式"""
with open('doc/mooc.csv', 'w') as f:
writer = csv.writer(f)
writer.writerows(courseinfo)
print('csv文件保存完毕...')
def save_json(courseinfo):
"""将获取的信息保存为json格式"""
with open('doc/mooc.json', 'w') as f:
# 每次只取一行信息
for item in courseinfo:
item = {
'name': item[0],
'studentNum': item[1],
'courseInfo': item[2],
'courseUrl': item[4],
'courseImgUrl': item[3]
}
# ensure_ascii: 如果有中文, 则设置为False, 表示使用Unicode编码, 中文不会乱码;
# indent=4: 所金为4个空格, 便于阅读;
# 编码为json格式
jsonitem = json.dumps(item, ensure_ascii=False, indent=4)
f.write(jsonitem)
print('json文件保存完毕...')
def moccSpider():
# 1). 爬取课程信息的第一页
url = 'http://www.imooc.com/course/list'
html = get_content(url)
courseinfo = parser_content(html)
# 列表, 保存第一页的课程信息
# 2). 如果有下一页信息, 则继续爬取课程内容;
# 如果没有下一页信息, 则跳出循环, 将课程信息保存到文件中.....;
while True:
selector = etree.HTML(html)
# 2). 什么时候爬取结束? 没有下一页的时候
# # 有下一页:
# <a href="/course/list/2?page=2">下一页</a>
# # 没有下一页:
# <span class="disabled_page">下一页</span>
# contains判断是否有下一页,如果有,则取href链接
nextPage = selector.xpath('//a[contains(text(),"下一页")]/@href')
# 只爬取前2页, 用于测试;如果想要全部爬取,if nextPage
if nextPage and ('3' not in nextPage[0]):
# 生成下一页的url地址
url = "http://www.imooc.com" + nextPage[0]
html = get_content(url)
other_courseinfo = parser_content(html)
courseinfo += other_courseinfo
else:
print('全部爬取结束...')
break
save_csv(courseinfo)
save_json(courseinfo)
def dealCourseData_csv(filename):
"""对于爬取的课程信息进行分析, 返回清洗好的数据"""
# 存储处理后生成的字符串信息
wordcloudString = ''
with open(filename) as f:
reader = csv.reader(f)
# 清洗需要分析的文本信息: 删除里面不必要的逗号, 句号, 表情;
# 正则表达式书写清除规则
pattern = re.compile(r'([\u4e00-\u9fa5]+|[a-zA-Z0-9]+)')
for item in reader:
# 将来进行词云展示时, 需要的是字符串, 而不是列表;
# 这里传入词云的是文字信息,所以链接人数不用写入
name = "".join(re.findall(pattern, item[0]))
detail = "".join(re.findall(pattern, item[2]))
wordcloudString += name
wordcloudString += detail
# 去除一些没有意义的词汇
return re.sub(r'(学习|使用|入门|基础|实现|掌握)', '', wordcloudString)
def gen_wordcloud(text, filename):
# 1,切割中文
result = jieba.lcut(text)
# 2,绘制词云,打开图片, 获取图片的数据信息;编辑图片为矩阵数据
imgobj = Image.open('doc/img.jpg')
img_mask = np.array(imgobj)
# 3). 创建词云对象, 设置属性
wcobj = wordcloud.WordCloud(
mask=img_mask, # 数据如何填充到图片
background_color='snow', # 背景颜色
font_path="/usr/share/fonts/wqy-zenhei/wqy-zenhei.ttc", # 如果是中文, 指定字体库(fc-list :lang=zh)
min_font_size=5, # 图片中最小的字体大小
max_font_size=50, # 图片中最小的字体大小
width=1000, # 图片宽度
height=1000, # 高
)
# 4). 生成图片;
# 词云绘制时, 默认之处理字符串类型, 每个单词必须以逗号分隔符分割
wcobj.generate(','.join(result))
# 生成图片
wcobj.to_file(filename)
print("生成图片%s成功......." % (filename))
if __name__ == '__main__':
moccSpider()
text = dealCourseData_csv('doc/mooc.csv')
filename = 'doc/mooc.png'
gen_wordcloud(text, filename)
csv保存的数据
json保存的数据
生成的词云