Python爬虫学习第三弹 —— Xpath 页面解析 & 实现无广百·度

早上好啊,大佬们。上回使用 Beautiful Soup 进行页面解析的内容是不是已经理解得十分透彻了~

这回我们再来尝试使用另外一种页面解析,来重构上一期里写的那些代码。

讲完Xpath之后,小白兔会带大家解决上期里百·度搜索的代码编写,保证会有收获的哦,大家好好看好好学。

Xpath

XPath(XML Path Language)是一种用于在 XML(可扩展标记语言)文档中定位节点的语言。它也可以用于 HTML(超文本标记语言)文档,因为 HTML 可以看作是 XML 的一个子集。XPath 通过路径表达式来选取 XML 文档中的节点或者节点集。

Xpath不用额外安装包。

语法规则

首先,肯定要讲的是语法规则。

它的语法也很简单,都是很容易的。

1. 【//】 根目录
2. 【/】 子目录
3. 【@】获取属性
4. 【text()】获取文本
5. contains(@class,'result')

Bs4代码用Xpath重构

Xpath表达式

操作与上期基本一致,我们只着眼于定位内容的部分,也就是书写 Xpath 表达式

我们包裹所有我们所需内容的是这里,也就是说它就是我们所要指向的大类。

//div[@class="Community"]

然后再往里走,指向我们所需内容。

//div[@class="Community"]/div[contains(@class,"active")]

最后指向储存链接

//div[@class="Community"]/div[contains(@class,"active")]/div/div/div[contains(@class,"content")]/a

由于Xpath是一级一级向下的,所以不会遇到Bs4当时的情况,它的指向性会更好一些。

然后,对于我们的文本内容,也是一样的,大家可以自己试试,我在这里直接放结果了。

//div[@class="Community"]/div[contains(@class,"active")]/div/div/div/a/p/span[contains(@class,"blog-text")]

这样我们就解决了Xpath表达式。

Python代码修改

我们可以先打开上次写的代码,对照着一样的思路,只需要修改其中几句就可以了。

首先,我们使用的是Xpath所以导入的包要改;

python 复制代码
from lxml import etree

然后,我们页面解析时候的语句也要改;

python 复制代码
soup=etree.HTML(html.text)

最后,把搜索语句修改了就完成了。

python 复制代码
urls = soup.xpath('//div[@class="Community"]/div[contains(@class,"active")]/div/div/div[contains(@class,"content")]/a')
titles = soup.xpath('//div[@class="Community"]/div[contains(@class,"active")]/div/div/div/a/p/span[contains(@class,"blog-text")]')

由于当时写的Bs4的代码有一些问题,所以最后输出要进行一些修改。

这里就是完整代码了------

python 复制代码
import requests
from lxml import etree

url = 'https://www.csdn.net/?spm=1011.2266.3001.4476'
headers={
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
}

html = requests.get(url,headers=headers)
soup=etree.HTML(html.text)

urls = soup.xpath('//div[@class="Community"]/div[contains(@class,"active")]/div/div/div[contains(@class,"content")]/a')
titles = soup.xpath('//div[@class="Community"]/div[contains(@class,"active")]/div/div/div/a/p/span[contains(@class,"blog-text")]')

for i in range(len(titles)):
    print(urls[i].get('href'))
    print(titles[i].text)

百·度搜索实现

上期最后,小白兔不是给了大家一个题目嘛,相信按照大家的聪明才智肯定都能写出来,这里小白兔还是提供一下我的思路。

百度搜索模拟

首先,我们手动先进行一次百度的搜索,看看怎么去获取我们所需要的内容。

例如我们搜索一下 Python 和 爬虫。

然后打开它们的检查,抓一下包,找到它的网址内容。

对于不同的网址搜索,改变的就是它的一些载荷

所以我们可以比较一下他们的区别,然后就能够找到搜索不同内容需要修改的内容。

我们很容易就能发现其中表示搜索内容的载荷 ------ wd

但是其中还是有很多参数是不同的。

所以这里我又进行了一次搜索,得到的结果如下:

可以发现那些不同的参数在搜索同一个内容时也是不一样的,说明它们不影响搜索内容。

我们看一下新的搜索结果,发现它返回的内容是不同的,说明那些参数是随机生成的,是影响这里的搜索结果的,所以我们可以不用管它们。

这些参数具体指什么,我还没学到,有大佬知道可以告诉一下。

OK,下面我们可以试一下,只修改 wd 参数能不能进入到不同的搜索结果。

https://www.baidu.com/s?wd=Python

https://www.baidu.com/s?wd=Java

显然我们的猜测是对的。

Python爬虫访问页面

那么,我们就先用爬虫来访问一下页面。

https://www.baidu.com/s?wd=Python\&rsv_spt=1\&rsv_iqid=0xb6f30fb0001dc9b1\&issp=1\&f=8\&rsv_bp=1\&rsv_idx=2\&ie=utf-8\&tn=baiduhome_pg\&rsv_dl=tb\&rsv_sug3=23\&rsv_enter=1\&rsv_sug1=9\&rsv_sug7=100\&rsv_sug2=0\&rsv_btype=t\&inputT=5324\&rsv_sug4=5626\&rsv_sug=1

我们就先按照我们直接搜索出的结果来进行访问。

python 复制代码
import requests

url = 'https://www.baidu.com/s?wd=Python&rsv_spt=1&rsv_iqid=0xb6f30fb0001dc9b1&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_dl=tb&rsv_sug3=23&rsv_enter=1&rsv_sug1=9&rsv_sug7=100&rsv_sug2=0&rsv_btype=t&inputT=5324&rsv_sug4=5626&rsv_sug=1'
headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
}
# 这里我们只需要给一个user-agent就能够返回了,所以我们就不用继续给Cookie 和 Referer等参数。

html = requests.get(url, headers=headers)
print(html.text)

但是,按照我们刚才推论出来的结果,我们用这个网址进行搜索,对于同一个 wd值 的返回的结果是固定的,这当然不是我们想要的。

所以我们可以把其它的参数都给删掉。

python 复制代码
"""
import requests

url = 'https://www.baidu.com/s?wd=Python'
headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
    'cookie':'BIDUPSID=B1F42D0D8BD6CE75C9B0290A9BAF2542; PSTM=1734239698; BAIDUID=B1F42D0D8BD6CE75087359BD19AEC05E:FG=1; BDUSS=Dh2dVNkLTQ0ZnZob2lWWGEzNXdZLTBubzZMZlhsMWhYUTNMb2FiSEJVM213SzVuSVFBQUFBJCQAAAAAAQAAAAEAAAAuxc1outqyu8CtvLjQobDXzcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOYzh2fmM4dnc; BDUSS_BFESS=Dh2dVNkLTQ0ZnZob2lWWGEzNXdZLTBubzZMZlhsMWhYUTNMb2FiSEJVM213SzVuSVFBQUFBJCQAAAAAAQAAAAEAAAAuxc1outqyu8CtvLjQobDXzcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOYzh2fmM4dnc; BD_UPN=12314753; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; delPer=0; BD_CK_SAM=1; PSINO=5; BAIDUID_BFESS=B1F42D0D8BD6CE75087359BD19AEC05E:FG=1; BA_HECTOR=2024ak058g8h2l0g0gah8180afd4as1jph43r1v; ZFY=pRGjK1fPQMj:Aq4XO1Q:ASRpcxNTPuaK66RZE1Jh5snKs:C; B64_BOT=1; H_PS_PSSID=61027_61542_61737_61782_61872_61878_61997_62001; BDRCVFR[feWj1Vr5u3D]=-_EV5wtlMr0mh-8uz4WUvY; baikeVisitId=dd0da186-dfcc-4b80-a830-a2e6ef3800e9; H_PS_645EC=bf09nMdMAx3qgm57o9DK9esArY%2FGSNJULT%2FUkOm6IqpNNWAGBqrHMEotjX3hI1z%2B2tOq; COOKIE_SESSION=29_0_4_9_0_3_1_0_4_3_0_0_0_0_0_0_0_0_1738052751%7C9%23257689_3_1734922612%7C2'

}
# 这里我们需要加上Cookie才行

html = requests.get(url, headers=headers)
print(html.text)

但是这样我们要加上Cookie,可能其它的参数和Cookie有所重复。

页面解析

下面我们来看看怎么去解析页面获取我们所需要的内容。

其中红框的内容是我们所需要的搜索结果。

方法就是和之前都一样的,这里就不多说了,直接看结果。

//div[@id='content_left']/div[contains(@class,"result")]/div/div/div/h3/a

上面是Xpath,下面是Bs4

div#content_left div.result.c-container.xpath-log.new-pmd h3 a

python 复制代码
#Xpath版
import requests
from lxml import etree

url = 'https://www.baidu.com/s?wd=Python'
headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
    'cookie':'BIDUPSID=B1F42D0D8BD6CE75C9B0290A9BAF2542; PSTM=1734239698; BAIDUID=B1F42D0D8BD6CE75087359BD19AEC05E:FG=1; BDUSS=Dh2dVNkLTQ0ZnZob2lWWGEzNXdZLTBubzZMZlhsMWhYUTNMb2FiSEJVM213SzVuSVFBQUFBJCQAAAAAAQAAAAEAAAAuxc1outqyu8CtvLjQobDXzcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOYzh2fmM4dnc; BDUSS_BFESS=Dh2dVNkLTQ0ZnZob2lWWGEzNXdZLTBubzZMZlhsMWhYUTNMb2FiSEJVM213SzVuSVFBQUFBJCQAAAAAAQAAAAEAAAAuxc1outqyu8CtvLjQobDXzcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOYzh2fmM4dnc; BD_UPN=12314753; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; delPer=0; BD_CK_SAM=1; PSINO=5; BAIDUID_BFESS=B1F42D0D8BD6CE75087359BD19AEC05E:FG=1; BA_HECTOR=2024ak058g8h2l0g0gah8180afd4as1jph43r1v; ZFY=pRGjK1fPQMj:Aq4XO1Q:ASRpcxNTPuaK66RZE1Jh5snKs:C; B64_BOT=1; H_PS_PSSID=61027_61542_61737_61782_61872_61878_61997_62001; BDRCVFR[feWj1Vr5u3D]=-_EV5wtlMr0mh-8uz4WUvY; baikeVisitId=dd0da186-dfcc-4b80-a830-a2e6ef3800e9; H_PS_645EC=bf09nMdMAx3qgm57o9DK9esArY%2FGSNJULT%2FUkOm6IqpNNWAGBqrHMEotjX3hI1z%2B2tOq; COOKIE_SESSION=29_0_4_9_0_3_1_0_4_3_0_0_0_0_0_0_0_0_1738052751%7C9%23257689_3_1734922612%7C2'
}

html = requests.get(url, headers=headers)

soup = etree.HTML(html.text)
divs = soup.xpath('//div[@id="content_left"]/div[contains(@class,"result")]/div/div/div/h3/a')
for div in divs:
    print(div.text)
    print(div.get('href'))
python 复制代码
#Bs4版
import requests
from bs4 import BeautifulSoup

url = 'https://www.baidu.com/s?wd=Python'
headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
    'cookie':'BIDUPSID=B1F42D0D8BD6CE75C9B0290A9BAF2542; PSTM=1734239698; BAIDUID=B1F42D0D8BD6CE75087359BD19AEC05E:FG=1; BDUSS=Dh2dVNkLTQ0ZnZob2lWWGEzNXdZLTBubzZMZlhsMWhYUTNMb2FiSEJVM213SzVuSVFBQUFBJCQAAAAAAQAAAAEAAAAuxc1outqyu8CtvLjQobDXzcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOYzh2fmM4dnc; BDUSS_BFESS=Dh2dVNkLTQ0ZnZob2lWWGEzNXdZLTBubzZMZlhsMWhYUTNMb2FiSEJVM213SzVuSVFBQUFBJCQAAAAAAQAAAAEAAAAuxc1outqyu8CtvLjQobDXzcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOYzh2fmM4dnc; BD_UPN=12314753; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; delPer=0; BD_CK_SAM=1; PSINO=5; BAIDUID_BFESS=B1F42D0D8BD6CE75087359BD19AEC05E:FG=1; BA_HECTOR=2024ak058g8h2l0g0gah8180afd4as1jph43r1v; ZFY=pRGjK1fPQMj:Aq4XO1Q:ASRpcxNTPuaK66RZE1Jh5snKs:C; B64_BOT=1; H_PS_PSSID=61027_61542_61737_61782_61872_61878_61997_62001; BDRCVFR[feWj1Vr5u3D]=-_EV5wtlMr0mh-8uz4WUvY; baikeVisitId=dd0da186-dfcc-4b80-a830-a2e6ef3800e9; H_PS_645EC=bf09nMdMAx3qgm57o9DK9esArY%2FGSNJULT%2FUkOm6IqpNNWAGBqrHMEotjX3hI1z%2B2tOq; COOKIE_SESSION=29_0_4_9_0_3_1_0_4_3_0_0_0_0_0_0_0_0_1738052751%7C9%23257689_3_1734922612%7C2'
}

html = requests.get(url, headers=headers)

soup = BeautifulSoup(html.text, 'lxml')
divs = soup.select('div#content_left div.result.c-container.xpath-log.new-pmd h3 a')
for div in divs:
    print(div.text.strip())
    print(div['href'])

两个的效果对比,还是Bs4更好一点,所以下面我们就继续用bs

4来写。

自定义搜索和翻页

我们下面来实现自定义的搜索,也就是我们来修改wd的值。

我们只需要加一个input,然后将输入的值替换wd。

python 复制代码
import requests
from bs4 import BeautifulSoup

search = input('请输入搜索内容:')
url = f'https://www.baidu.com/s?wd={search}'
headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
    'cookie':'BIDUPSID=B1F42D0D8BD6CE75C9B0290A9BAF2542; PSTM=1734239698; BAIDUID=B1F42D0D8BD6CE75087359BD19AEC05E:FG=1; BDUSS=Dh2dVNkLTQ0ZnZob2lWWGEzNXdZLTBubzZMZlhsMWhYUTNMb2FiSEJVM213SzVuSVFBQUFBJCQAAAAAAQAAAAEAAAAuxc1outqyu8CtvLjQobDXzcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOYzh2fmM4dnc; BDUSS_BFESS=Dh2dVNkLTQ0ZnZob2lWWGEzNXdZLTBubzZMZlhsMWhYUTNMb2FiSEJVM213SzVuSVFBQUFBJCQAAAAAAQAAAAEAAAAuxc1outqyu8CtvLjQobDXzcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOYzh2fmM4dnc; BD_UPN=12314753; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; delPer=0; BD_CK_SAM=1; PSINO=5; BAIDUID_BFESS=B1F42D0D8BD6CE75087359BD19AEC05E:FG=1; BA_HECTOR=2024ak058g8h2l0g0gah8180afd4as1jph43r1v; ZFY=pRGjK1fPQMj:Aq4XO1Q:ASRpcxNTPuaK66RZE1Jh5snKs:C; B64_BOT=1; H_PS_PSSID=61027_61542_61737_61782_61872_61878_61997_62001; BDRCVFR[feWj1Vr5u3D]=-_EV5wtlMr0mh-8uz4WUvY; baikeVisitId=dd0da186-dfcc-4b80-a830-a2e6ef3800e9; H_PS_645EC=bf09nMdMAx3qgm57o9DK9esArY%2FGSNJULT%2FUkOm6IqpNNWAGBqrHMEotjX3hI1z%2B2tOq; COOKIE_SESSION=29_0_4_9_0_3_1_0_4_3_0_0_0_0_0_0_0_0_1738052751%7C9%23257689_3_1734922612%7C2'
}

html = requests.get(url, headers=headers)

soup = BeautifulSoup(html.text, 'lxml')
divs = soup.select('div#content_left div.result.c-container.xpath-log.new-pmd h3 a')
for div in divs:
    print('标题文本:', div.text.strip())
    print('跳转链接:', div['href'])
    print('-------------------------------------------------------------------------------------------')

在百度搜索的最后有一个翻页的功能,这个我们也能够实现。

这是它搜索的 2、3 页,我们观察它的载荷,显而易见pn是我们所需要的翻页。

它是按照 10 为间隔,0是第一页,10是第二页,以此类推。

下面我们可以显示前十页的内容。

python 复制代码
import requests
from lxml import etree
from bs4 import BeautifulSoup

search = input('请输入搜索内容:')
for i in range(0, 100, 10):
    url = f'https://www.baidu.com/s?wd={search}&pn={i}'
    headers = {
        'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
        'cookie':'BIDUPSID=B1F42D0D8BD6CE75C9B0290A9BAF2542; PSTM=1734239698; BAIDUID=B1F42D0D8BD6CE75087359BD19AEC05E:FG=1; BDUSS=Dh2dVNkLTQ0ZnZob2lWWGEzNXdZLTBubzZMZlhsMWhYUTNMb2FiSEJVM213SzVuSVFBQUFBJCQAAAAAAQAAAAEAAAAuxc1outqyu8CtvLjQobDXzcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOYzh2fmM4dnc; BDUSS_BFESS=Dh2dVNkLTQ0ZnZob2lWWGEzNXdZLTBubzZMZlhsMWhYUTNMb2FiSEJVM213SzVuSVFBQUFBJCQAAAAAAQAAAAEAAAAuxc1outqyu8CtvLjQobDXzcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOYzh2fmM4dnc; BD_UPN=12314753; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; delPer=0; BD_CK_SAM=1; PSINO=5; BAIDUID_BFESS=B1F42D0D8BD6CE75087359BD19AEC05E:FG=1; BA_HECTOR=2024ak058g8h2l0g0gah8180afd4as1jph43r1v; ZFY=pRGjK1fPQMj:Aq4XO1Q:ASRpcxNTPuaK66RZE1Jh5snKs:C; B64_BOT=1; H_PS_PSSID=61027_61542_61737_61782_61872_61878_61997_62001; BDRCVFR[feWj1Vr5u3D]=-_EV5wtlMr0mh-8uz4WUvY; baikeVisitId=dd0da186-dfcc-4b80-a830-a2e6ef3800e9; H_PS_645EC=bf09nMdMAx3qgm57o9DK9esArY%2FGSNJULT%2FUkOm6IqpNNWAGBqrHMEotjX3hI1z%2B2tOq; COOKIE_SESSION=29_0_4_9_0_3_1_0_4_3_0_0_0_0_0_0_0_0_1738052751%7C9%23257689_3_1734922612%7C2'
    }

    html = requests.get(url, headers=headers)

    soup = BeautifulSoup(html.text, 'lxml')
    divs = soup.select('div#content_left div.result.c-container.xpath-log.new-pmd h3 a')
    for div in divs:
        print('标题文本:', div.text.strip())
        print('跳转链接:', div['href'])
        print('-------------------------------------------------------------------------------------------')

如上,我们的无广百·度就实现了。

尾声

大佬们,Xpath的内容就到这里了,和Bs4的处理基本也是一样的,今天写的所有代码我会在下面通过网盘的方式提供给大家,可以用来复习一下。

链接:小白兔的礼物------Xpath学习

提取码:BpWS

大家可以自行去多爬一些网页,多多熟练一下。

下一回我们来学 正则表达式 ,正则是最全能的一个,当前面两个不能用的时候,我们就需要用上我们的正则。

相关推荐
DES 仿真实践家13 分钟前
【Day 11-N22】Python类(3)——Python的继承性、多继承、方法重写
开发语言·笔记·python
云泽野5 小时前
【Java|集合类】list遍历的6种方式
java·python·list
IMPYLH6 小时前
Python 的内置函数 reversed
笔记·python
科技苑8 小时前
简单 Python 爬虫程序设计
爬虫
小赖同学啊8 小时前
物联网数据安全区块链服务
开发语言·python·区块链
码荼9 小时前
学习开发之hashmap
java·python·学习·哈希算法·个人开发·小白学开发·不花钱不花时间crud
武昌库里写JAVA9 小时前
Oracle如何使用序列 Oracle序列使用教程
java·开发语言·spring boot·学习·课程设计
小陈phd10 小时前
李宏毅机器学习笔记——梯度下降法
人工智能·python·机器学习
kk爱闹10 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
Blossom.11810 小时前
机器学习在智能建筑中的应用:能源管理与环境优化
人工智能·python·深度学习·神经网络·机器学习·机器人·sklearn