xpath的运用
前提条件:
(1)需要pip install lxml
(2)from lxml import etree
(3)本地文件:tree = etree.parse(文件名)
(4)网络文件:tree = etree.HTML(网页字符串)
(5)ret = tree.xpath(),[注]:ret是一个列表
这样就可以使用了。
1.xpath的基础知识:
(1).常用的路径表达式:
//:不考虑位置的查找
./:从当前结点开始往下查找
@:选取属性
(2).实例:
/bookstore/book:选取根节点bookstore下面所有直接子节点book
//book:选取所有的book节点
bookstore/book[1]:查找bookstore里面的第一个book
/bookstore/book[last()]:选取bookstore里面的最后一个book节点
/bookstore/book[position()<3]:选取bookstore里面的前两个book节点
//title[@lang]:选取所有带有lang属性的title节点
//title[@lang='eng']:选取所有带有lang属性并且属性值为eng的title
(3).属性定位:
//input[@id="kw"]:选取id属性值为kw的input
//input[@class="bg s_btn"]:选取class属性值为bg或者是s_btn的input标签
(4).索引定位:
//div[@id="head"]/div/div[2]/a[@class="toindex"]
[注]:索引从1开始
(5).逻辑运算:
//input[@class="s_ipt" and @name="wd"]
(6).模糊匹配:
contains://input[contains(@class,"s_i")]选取所有class属性包含s_i的Input标签
contains://input[contains(text(),"爱"):选取所有文本标签包含爱这个字的input标签
starts-with://input[starts-with(@class,"s")]:选取所有class属性以s开头的input标签
(7).取文本:
//div[@id="u1"]/a[5]/text():选取id属性值为u1的div标签下的第5个a的文本内容
(8).取属性:
//div[@id="u1"]/a[5]/@href:选取id属性值为u1的div标签下的第5个a的href属性值
【注】:大部分的xpath返回结果是一个列表,并且下标是从1开始的,而不是0
爬取好段子的代码:
import re
import urllib.request
import urllib.parse
from lxml import etree
data_list = [] # 存放数据列表
def hanlde_request(url):
# 请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 Edg/91.0.864.54'
}
request = urllib.request.Request(headers=headers,url=url)
# 返回请求对象
return request
def parse_data(text):
tree = etree.HTML(text)
# //*[@id="LR"]/div/div[2]
div_ele = tree.xpath("//*[@id='LR']/div/div[2]") # xpath返回的都是列表
li_ele = div_ele[0].xpath(".//ul//li") # 得到所有的li标签元素
for li in li_ele:
nick = li.xpath(".//div[@class='head']/span/text()") # 获取用户名
title = li.xpath(".//div[@class='head']/h2/text()")
content = li.xpath(".//div[@class='content']/a//text()") #这里有的a标签里面有p标签有的有没有,所以要提取除标签以外的所有文本需要用//
data_dict = {
"nick":str(nick)[2:-2],
"title":str(title)[2:-2],
"content":str(re.sub(r'\\n\\u3000\\u3000','',str(content)))[2:-2] # 正则替换,加字符串替换
}
data_list.append(data_dict)
return data_list
def save_data(data):
for data_dict in data:
h1 = "<h1>{}</h1>".format(data_dict['title'])
p = "<p>{}</p>".format(data_dict['content'])
span = "<span>{}</span>".format(data_dict['nick'])
le = h1+p+span
# 这里自己还需要做一些处理,比如文本中含有\n还有就是需要先建立一个html文件
with open('b.html','a',encoding='utf8') as fp:
fp.write(le)
def main(start_page, end_page):
for pg in range(start_page,end_page+1):
url = 'http://www.haoduanzi.com/category/?1-{}.html'
url = url.format(pg) # 拼接地址
request = hanlde_request(url)
text = urllib.request.urlopen(request).read().decode() # 获取请求文本内容
data = parse_data(text) # 解析数据
save_data(data) # 保存数据
if __name__ == '__main__':
start_page = int(input('请输入开始页:'))
end_page = int(input("请输入结束页:"))
main(start_page, end_page)
这里还有许多不足的地方,还请大佬们多多指教,比如怎么更快的把指定内容写入到指定文件夹的指定位置,方法有一个就是:把原有文件读取到列表中,再把指定内容插入到指定位置,最后再把它写入到文件中,但是这样既耗时有耗费空间。所以还请大佬指教。
这里重要的就是了解xpath的基本语法,虽然浏览器提供了复制xpath的路径,但是我认为一开始学还是掌握基础比较好,毕竟基础好了,后面就简单了。在xpath里面两个点就是:1.读取下标是从0开始的2.返回的是列表类型的数据。