爬虫之数据提取

发布于:2024-10-17 ⋅ 阅读:(12) ⋅ 点赞:(0)

HTML数据提取

这一片文章, 我们一起学习如何利用HTML标签来提取数据。

我们打开二手房网站:
在这里插入图片描述

我们打开开发者工具, 找到请求:

在这里插入图片描述

这次我们找的请求, 和以前的不一样了, 所以这里面带大家找一找, 以前我们找的请求都是json格式的响应数据, 那今天由于我们要学习如何提取html数据, 我们今天找的请求的响应就必须市html格式的数据。

我们找到数据以后, 将url, 请求头的user-agent全部找出来, 并写到代码里面去, 这个和以前操作是一样的。

url = 'https://cs.lianjia.com/ershoufang/rs/'
headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
}

然后我们需要把这个请求里面的html格式的数据全部爬下来, 并且保存到一个文件当中:

import requests
headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
    "referer": "https://hip.lianjia.com/",
    "cookie": "select_city=430100; lianjia_ssid=18717f43-a946-4e0f-a774-7965c8aa73ed; lianjia_uuid=0741e41c-75be-4e7b-9bd0-ee4002203371; sajssdk_2015_cross_new_user=1; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%22192752ebbdd1116-0ed7d9ff3e4d3e-26001051-1474560-192752ebbded87%22%2C%22%24device_id%22%3A%22192752ebbdd1116-0ed7d9ff3e4d3e-26001051-1474560-192752ebbded87%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%7D; _jzqckmp=1; _ga=GA1.2.1019355060.1728542865; _gid=GA1.2.344285568.1728542865; hip=vxXEKT3nj90U2y57pSYlx074hLYy_KITMLesLlcpGMh9Slf8YMXZvf6QAv4ZcLnkesWaYhh-nRlvZVlTmOjIT-Y-WHy-FZE7aLT3xJpXyb0QTDqy9NYovzxBro7rK3M3NlC9A0EE8fu1MXkSBUrVvLakvFPxaOW6Z1j6eke9A-aD546zbHzuKX3T4Q%3D%3D; Hm_lvt_46bf127ac9b856df503ec2dbf942b67e=1728542848,1728543853; Hm_lpvt_46bf127ac9b856df503ec2dbf942b67e=1728543853; HMACCOUNT=7AB3E94A75916BE3; _qzja=1.151913534.1728542860751.1728542860751.1728543853745.1728542860751.1728543853745.0.0.0.2.2; _qzjc=1; _qzjto=2.2.0; _jzqa=1.489454228011104260.1728542851.1728542851.1728543854.2; _jzqc=1; _jzqx=1.1728543854.1728543854.1.jzqsr=hip%2Elianjia%2Ecom|jzqct=/.-; srcid=eyJ0Ijoie1wiZGF0YVwiOlwiYmIwMmYyYzU1ODZjMjNhZGJjOGVmZTZmYmEyYzVlODQ0OGRkNGYxYjJjZjliZGY4MDZjMmExOTgwOThkYjVkMzFkOTEwOTc5NTliOGNlMzBmMWNhZGJiN2NhYTY3ZTE0OTQ3NDc2YTg4N2JmYTBiOTRhODJlMTZiYjdmY2UxMjdhMDljY2UxYTY0M2RhMTlhMzQyN2ZlYTc5MTFkZTdkMmY5NzQyZmRjMTRmYTRmNjk0NGNmYmM4ZjYzOTBlMjE4YThhYWQ2ZGUyZTRkZmE5ZjU2OGIxZmJmNzBiZGQzY2E5ZWEyYzEzZmY2ZTMyOTlkOGFkMDUzNDQ0NmNiZTVhZFwiLFwia2V5X2lkXCI6XCIxXCIsXCJzaWduXCI6XCI5YzhiMDQ2OVwifSIsInIiOiJodHRwczovL2NzLmxpYW5qaWEuY29tL2Vyc2hvdWZhbmcvcnMvIiwib3MiOiJ3ZWIiLCJ2IjoiMC4xIn0=; _jzqb=1.1.10.1728543854.1; _qzjb=1.1728542860751.2.0.0.0; _ga_4JBJY7Y7MX=GS1.2.1728542865.1.1.1728543871.0.0.0"
}
url = 'https://cs.lianjia.com/ershoufang/rs/'
res = requests.get(url,headers=headers)
print(res.text)
with open('链家.html','w',encoding='utf-8')as f:
    f.write(res.text)

这里说明下, 后面有referer和cookie是为了防止被识别是爬虫程序, 博主在爬虫的过程中, 前面几次爬虫就是因为没有加referer和cookie, 结果没有把数据成功爬下来, 因为被网站视为是爬虫程序了。

运行代码后, 在代码的同级目录下, 会多出一个新的html文件。

在这里插入图片描述

打开文件:

在这里插入图片描述

我们发现就是我们找到的请求里面的响应内容, 我们给它爬下来并且将内容保存到了’链家.html’文件中。

我们需要用到html文件干什么呢?

我们需要用到html文件里面的html标签, 最终的目的是提取html标签里面的数据

那我们怎么提取数据呢?

这就是我们这篇文章要讲到的, 用xpath爬取数据, 在使用xpath之前, 我们需要安装lxml。

安装命令:

pip install lxml

lxml: 解析html的一个解析器, 用来提取html数据。

我们再使用xpath之前, 需要导入安装包:

from lxml import etree

然后使用etree的HTML函数, 参数传入的是html字符串, 为了解析html字符串文本的数据。

# 避免多次请求,提前将要解析的数据保存在了本地html文件中
# 提取数据,需要把文件中的字符串给读取出来
with open('链家.html','r',encoding='utf-8') as f:
    html_code = f.read()
tree = etree.HTML(html_code)

我们刚才把请求html的数据并且保存到这个文件里面, 那我们需要读取刚才我们保存文件里面的数据, 用到with open(‘链家.html’,‘r’,encoding=‘utf-8’) as f这句话。将文件中获取到的数据, 进行html解析。

xpath用法:

一个杠(/):
tree.xpath('/html')

这个是为了获取html标签, 最左侧/:表示当前xpath表达式一定要从根标签开始定位。

print(tree.xpath('/html/head/title'))

非最左侧/:表示一个层级, 就是获取html标签中的head标签里面的title标签。

特点: 必须从跟标签开始定位, 最前面是/html

两个杠(//):
print(tree.xpath('//title'))

最左侧的//: 从html中的任意位置找标签, 不需要再从跟标签html开始了。

这段代码的意思是获取所有的title标签

print(tree.xpath('//div'))

获取所有的div标签

通过text()在我们获取到的标签里面的值(就是文本数据):
print(tree.xpath('//span/text()'))

获取标签的内容 获取网页中所有的span标签的文本内容。

两个杠相比于一个杠的用法来讲, 更加的灵活, 不过也有缺点, 就是一个网页, 会有很多相同的标签, 那我们到底要定位到哪个标签, 光靠我们讲的 / 和 // 肯定是不够的, 我们接下来要讲如何准确的定位到自己想要的标签。

如何准确的定位到自己想要的标签

那么想要解决上面所说的准确的定位的问题, 解决办法有两个:

第一钟方法:

通过父级标签来做限定, 使用这种方法的常用场景:目标标签没有任何的属性特征。

print(tree.xpath('//h2/span/text()'))

从当前网页中找h2标签的儿子span标签,获取span标签的文本内容, 此时, h2就是span的父级标签。

第二种方法:

利用属性来进行筛选以做到准确定位。就是说方我们看到网页有标签长这样:<标签名 属性名=属性值 > 文本内容 </标签名>, 我们就可以考虑使用属性名来定位了。

语法: 标签名[@属性名=“属性值”]

比如, 我们要获取这个a标签里面的文本:

<a class="" href="https://cs.lianjia.com/ershoufang/104113837527.html" target="_blank" data-log_index="1" data-el="ershoufang" data-housecode="104113837527" data-is_focus="" data-sl="">很安静的小高层,得房率高,全新精装修四居二卫</a>

我们可以这么写:

print(tree.xpath('//a[@href="https://cs.lianjia.com/ershoufang/104113837527.html"]/text()'))
我们再举个例子, 用第二种写法解决。

例子:获取网页中的div标签,并且div的标签身上必须要有data-price="16495"属性的儿子span标签的文本数据

代码:

print(tree.xpath('//div[@data-price="16495"]/span/text()'))
获取标签里面的属性值

语法: 标签/@属性名

比如, 我们要获取一个div的类名为info clear(class = info clear), div里面有个a标签, 获取a标签里面的href属性的值。

print(tree.xpath('//div[@class="info clear"]//a/@href'))

我们已经把xpath的内容讲完了, 那我们接下来就讲一个案例:

这个案例, 就是我们刚才打开过的二手房网站, 我们的这个案例就是利用xpath来爬取网站里面的数据, 要求爬取到标题和总价。

在这里插入图片描述

代码:

from lxml import etree

# 避免多次请求,提前将要解析的数据保存在了本地html文件中
# 提取数据,需要把文件中的字符串给读取出来
with open('链家.html','r',encoding='utf-8')as f:
    html_code = f.read()
tree = etree.HTML(html_code)

lis = tree.xpath('//ul[@class="sellListContent"]/li') # 30个房屋信息的整体

for li in lis:
    #     第一次循环 li=第一个房子信息的整体对象
    # 第一次循环,li.xpath 通过编写的xpath语法 从当前第一个li标签中去匹配内容
    # 配合.进行使用:代表当前标签
    title = li.xpath('.//div[@class="title"]/a/text()')[0]
    price = li.xpath('.//div[@class="totalPrice totalPrice2"]//text()')
    # [' ', '220', '万'] ---》 220万
    price = ''.join(price)

    # 获取标题和总价
    print(title, price)

思路, 我们可以先获取到大范围的标签, 确保我们要爬取的数据, 都在大标签的范围之内, 然后再依次去找我们要爬取的数据的小标签。

注意: .//div[@class=“title”]/a/text(), 最前面要加点号(.)

结果:

在这里插入图片描述

实战:

把剩下再框内的所有信息, 全部爬取。(依然还是用刚才的二手房网站)。

剩下还有房子信息, 房子单价, 大致地址。

我们总共有5个信息要爬, 分别是标题, 大致地址, 房子信息, 房子单价, 房子总价。

先自己尝试做一做哦, 不要马上看答案。

参考答案:

from lxml import etree

with open('链家.html', 'r', encoding='utf-8') as f:
    html_code = f.read()
tree = etree.HTML(html_code)
info_ershoufang = tree.xpath('//div[@class="info clear"]')
print(info_ershoufang)
for i in info_ershoufang:
    title = i.xpath('.//div[@class="title"]//text()')
    print("标题:", ''.join(title))
    address = i.xpath('.//div[@class="positionInfo"]//text()')
    print("大致地址:", ''.join(address).replace(" ", ""))
    house_info = i.xpath('.//div[@class="houseInfo"]//text()')
    print("房子信息:", ''.join(house_info).replace("|", "、").replace(" ", ""))
    unit_price = i.xpath('.//div[@class="unitPrice"]//text()')
    print("房子单价:", ''.join(unit_price))
    totalPrice = i.xpath('.//div[@class="totalPrice totalPrice2"]//text()')
    print("房子总价:", ''.join(totalPrice).replace(" ", ""))
    print()

你答对了吗? 如果答出来的话, 给自己一个掌声哦!!!👏

以上就是爬虫之html数据提取的所有内容了, 如果有哪里不懂的地方,可以把问题打在评论区, 欢迎大家在评论区交流!!!
如果我有写错的地方, 望大家指正, 也可以联系我, 让我们一起努力, 继续不断的进步.
学习是个漫长的过程, 需要我们不断的去学习并掌握消化知识点, 有不懂或概念模糊不理解的情况下,一定要赶紧的解决问题, 否则问题只会越来越多, 漏洞也就越老越大.
人生路漫漫, 白鹭常相伴!!!