python爬虫从入门到放弃之十六:Xpath简化

1. 什么是Xpath
  • 解析XM语言的一种语言(HTML其实是XML的子级),广泛用于解析HTML数据
  • 几乎所有语言都能使用xpath,比如Java和C语言
  • 除了xpath还有其他手段用于XML解析,比如lxml、bs4等

2. Xpath语法
  • 层级:/直接子级      //跳级
  • 节点:.当前节点      ..当前父节点
  • 属性:@直接属性访问      contains()包含属性访问
  • 索引:[1]第一个、[2]第二个......[last()-1]倒数第二个、[last()]最后一个
  • 文本:text()提取文本

3. 使用xpath

在浏览器中是有xpath的,通过在浏览器的练习,可以快速上手

示例:打开浏览器,打开百度,输入xpath,我们就搜索xpath好了,如下:

python爬虫从入门到放弃之十六:Xpath简化_第1张图片

按F12→Element →按ctrl+F

python爬虫从入门到放弃之十六:Xpath简化_第2张图片

我们输入一个最简单的xpath://title,找title标签,这时浏览器就帮我们找出来

用代码实现:

import requests
from lxml import etree

r = requests.get('http://www.baidu.com/s?wd=xpath')

html = etree.HTML(r.text)
print(html,type(html))

title = html.xpath('//title')
print(title,type(title))

title = html.xpath('//title/text()')
print(title,type(title))

运行结果:

 
[] 
['xpath_百度搜索'] 
>>> 

可以发现,利用etree.HTML,将字符串转化为Element对象,Element对象具有xpath的方法,返回结果的列表

//title就是我们找的title标签,如果我们直接去打印它,只能看到它的内存地址

我们可以通过/text()取出标签中的文本,/@属性名取出属性的值

接下来我们找一个带属性的标签

python爬虫从入门到放弃之十六:Xpath简化_第3张图片

可以看到,//div[@class="FYB_RD"],这就是找一个带属性的标签示例了,我们可以看到它显示只有一个:1 of 1,如果我们直接//div那你会发现出来一大坨,这显然不是我们想要的!

此时,可以看到"搜索热点"所在的标签在

子级下的第一个div标签,用//div[@class="FYB_RD"]/div[1]就可以拿到了,我们还可以用属性访问来提取

代码实现:

import requests
from lxml import etree

r = requests.get('http://www.baidu.com/s?wd=xpath')

html = etree.HTML(r.text)

search_hot1= html.xpath('//div[@class="FYB_RD"]/div[1]/@title')
print(search_hot1)

search_hot2= html.xpath('//div[@class="cr-title opr-toplist1-title"]/@title')
print(search_hot2)

search_hot3= html.xpath('//div[contains(@class,"opr-toplist1-title")]/@title')
print(search_hot3)

运行结果:

['搜索热点']
['搜索热点']
['搜索热点']
>>> 

以上,我们通过三种方式取出这个div标签的title属性的值,最后一种方式包含属性访问的,因为"opr-toplist1-title"并不是class的全部属性值,它只是包含了这一部分,所以要用contains()函数

接下来看一下节点的问题,在//div[@class="FYB_RD"]后面加上/./..

python爬虫从入门到放弃之十六:Xpath简化_第4张图片

python爬虫从入门到放弃之十六:Xpath简化_第5张图片

可以看到//div[@class="FYB_RD"]/.等价于//div[@class="FYB_RD"],而//div[@class="FYB_RD"]/..则是//div[@class="FYB_RD"]的父亲标签,这里指的是它的父标签,自然是一个,并不代表//div[@class="cr-content "]就是一个,我们试试看

python爬虫从入门到放弃之十六:Xpath简化_第6张图片

可以看到//div[@class="cr-content "]找出两个,第二个是//div[@class="FYB_RD"]的父标签

那么这个.代表的当前节点有什么用途呢?

其实,它主要用于二次xpath的节点本身,例如我们第一次取出//div[@class="cr-content "],接着取它下面的子孙级,就用上.

示例代码:

import requests
from lxml import etree

r = requests.get('http://www.baidu.com/s?wd=xpath')
html = etree.HTML(r.text)

content= html.xpath('//div[@class="cr-content "]')[1]
print(content)
fyb = content.xpath('./div[@class="FYB_RD"]/@class')
print(fyb)

运行结果:


['FYB_RD']
>>> 

接下来我们来取出今天的50个搜索热点

python爬虫从入门到放弃之十六:Xpath简化_第7张图片

通过在浏览器的测试,我们可以实行一行代码取出50个搜索热点所在的a标签

代码实现:

import requests
from lxml import etree

r = requests.get('http://www.baidu.com/s?wd=xpath')
html = etree.HTML(r.text)
search_hot= html.xpath('//div[@class="FYB_RD"]//tbody/tr//a/@title')
print(search_hot)

这时,我们取出了搜索热点的标题,下面我们点开一个搜索热点

python爬虫从入门到放弃之十六:Xpath简化_第8张图片

可以看到,有五家新闻报道,我们来看看怎么取出对应的链接

python爬虫从入门到放弃之十六:Xpath简化_第9张图片
python爬虫从入门到放弃之十六:Xpath简化_第10张图片

代码实现:

import requests
from lxml import etree


# 获取解析后的页面
def get_html(url):
    s = requests.Session()
    r = s.get(url)
    html = etree.HTML(r.text)
    return html

# 获取搜索热点
def get_search_hots():
    html = get_html('http://www.baidu.com/s?wd=xpath')
    search_hots= html.xpath('//div[@class="FYB_RD"]//tbody/tr//a/@title')
    hots_dict={}
    for index,word in enumerate(search_hots):
        print(index,word)
        hots_dict[str(index)] = word
    return hots_dict


# 获取搜索热点的提交网址
def get_hot_url(word):
    url = 'http://www.baidu.com/s?wd='+word
    return url
  

# 获取搜索热点的新闻报道
def get_news(url):
    html = get_html(url)
    links = html.xpath('//div[@class="c-offset"]/div//a/@href')
    times = html.xpath('//div[@class="c-offset"]/div//span[1]/text()')
    news = html.xpath('//div[@class="c-offset"]/div//span[2]/text()') 
    links = [requests.get(link).url for link in links]
    for new,time,link in zip(news,times,links):
        print(new,time,link)

def run():
    hots_dict = get_search_hots()    
    while True:
        index = input('\n请输入对应的序号查看新闻报道:')
        if index not in hots_dict:
            continue
        word = hots_dict[index]
        url = get_hot_url(word)
        get_news(url)


if __name__ == "__main__":
    print('最新的百度热搜如下:\n')
    try:
        run()
    except:
        print('产生异常!爬取失败...')

运行结果:

最新的百度热搜如下:

0 华为预测十大趋势
1 潘粤明 绯闻女友
2 利奇马最大风力
3 歌手平安喜获二胎
4 鸿蒙操作系统开源
5 老赖藏5500万珠宝
6 青岛发布道歉
7 郎朗机场亲密挽手
8 李嫣为王菲画像
9 李保芳谈茅台涨价
10 阿sir发来感谢信
11 首个台风红色预警
12 9号利奇马台风
13 华为正式发布鸿蒙
14 北京奥运会11周年
15 中兴通讯跌停
16 柳岩称暧昧不道德
17 苏州商业街爆炸
18 买茅台人脸识别
19 魏大勋否认恋情
20 中日重启战略对话
21 TFBOYS报平安
22 萧亚轩告白粉丝
23 大润发私罚小偷
24 香港局势座谈会
25 小S全家福曝光
26 陆毅女儿晒自拍
27 黄明昊坐轮椅现身
28 比斯利被禁赛5场
29 网红名字被抢注
30 刘湘破世界纪录
31 张馨予妈妈受伤
32 主持人涂磊道歉
33 河南6名儿童溺亡
34 香港两大巴车相撞
35 使徒行者2上映
36 魏大勋杨幂
37 胡歌薛佳凝聚餐
38 日本偶遇王思聪
39 香港光头警长回信
40 七夕情侣扎堆领证
41 哪吒票房破30亿
42 潘粤明女友探班
43 乔碧萝全网黑名单
44 杭州现七彩祥云
45 大陆暂停参加金马
46 易烊千玺红眼航班
47 苹果遭集体诉讼
48 范冰冰七夕自拍
49 中国男篮全新战袍

请输入对应的序号查看新闻报道:0
前瞻网 1天前 https://baijiahao.baidu.com/s?id=1641285641204066160&wfr=spider&for=pc
金融界 1天前 https://baijiahao.baidu.com/s?id=1641266819972047150&wfr=spider&for=pc
网易 1天前 http://news.163.com/19/0808/19/EM32LML800019K82.html
新京报 1天前 https://baijiahao.baidu.com/s?id=1641286241207755953&wfr=spider&for=pc
川北在线 18小时前 http://www.guangyuanol.cn/news/roll/2019/0808/983647.html

请输入对应的序号查看新闻报道:



>>>阅读更多文章请点击以下链接:

python爬虫从入门到放弃之一:认识爬虫
python爬虫从入门到放弃之二:HTML基础
python爬虫从入门到放弃之三:爬虫的基本流程
python爬虫从入门到放弃之四:Requests库基础
python爬虫从入门到放弃之五:Requests库高级用法
python爬虫从入门到放弃之六:BeautifulSoup库
python爬虫从入门到放弃之七:正则表达式
python爬虫从入门到放弃之八:Xpath
python爬虫从入门到放弃之九:Json解析
python爬虫从入门到放弃之十:selenium库
python爬虫从入门到放弃之十一:定时发送邮件
python爬虫从入门到放弃之十二:多协程
python爬虫从入门到放弃之十三:Scrapy概念和流程
python爬虫从入门到放弃之十四:Scrapy入门使用
python爬虫从入门到放弃之十五:ScrapyScrapy爬取多个页面
python爬虫从入门到放弃之十六:Xpath简化
python爬虫从入门到放弃之十七:常见反爬手段
python爬虫已放弃,视频教程资源来领取

你可能感兴趣的:(python爬虫从入门到放弃之十六:Xpath简化)