python 爬虫 数据提取

本文深入探讨了XPath与CSS选择器在网页数据抓取中的应用,通过实例讲解了如何利用这些工具精准定位和提取所需信息,特别强调了在Python环境下使用lxml与BeautifulSoup库进行数据解析的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

结构化数据

类似于动态加载的 先有结构后有数据
json

非结构化数据

现有数据 后有结构

正则

个人感觉,正则是匹配数据最快的,但也是最难的。
之前写过正则的匹配,这里就不多说了。

Xpath

表达式描述
/从根节点开始
//从匹配选择的当前节点选择文档中的节点,不考节点虑位置
.选取当前节点
选取当前节点的父节点
/bookstore/book[1]选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()]选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position() < 3]选取属于 bookstore 元素的子元素的最前面的两个 book 元素。
//title[@lang=“xxxx”]选取所有拥有名为 lang 的属性为xxxx的 title 元素。
@选取属性
text()选取文本内容
*匹配任何元素节点。
@*匹配任何属性节点。
node()匹配任何类型的节点。

栗子说:“来人,上干货!!”

from lxml import etree
import requests
	response = requests.get('https://bj.lianjia.com/zufang')
	html = etree.HTML(response.text)
    ul_list = html.xpath('//ul[@id="house-lst"]/li')
    for li in ul_list:
        dic = {}
        # 图片链接
        dic['img_url'] = li.xpath('./div[@class="pic-panel"]//img/@src')[0]
        # 标题
        dic['title'] = li.xpath('.//div[@class="info-panel"]/h2/a/text()')[0]
        # 四个地址
        dic['address'] = '| '.join(li.xpath('.//div[@class="info-panel"]//div[@class="where"]//span/text()'))
        # 房屋详情
        dic['other'] = ' |'.join(li.xpath('.//div[@class="info-panel"]//div[@class="con"]/text()') + \
                                 li.xpath('.//div[@class="info-panel"]//div[@class="con"]/a/text()'))
        # 价格
        dic['price'] = li.xpath('.//div[@class="price"]/span/text()')[0]
        # 更新
        dic['up_date'] = li.xpath('.//div[@class="price-pre"]/text()')[0]
        # 看过
        dic['look'] = li.xpath('.//div[@class="square"]//span/text()')[0] + '看过'
        print(dic)
BeautifulSoup / CSS 选择器
  • prettify() 可以将html代码格式化输出
  • find()----查找第一个节点
    • 参数:
      name :可以是字符串,列表,正则表达式 (标签的名称)
      attrs:收一个字典(标签的属性)
      text:字符串,列表(查找出所有根text文本一样的内容)
  • find_all():查找所有的节点  用法和find一样

    bs4.BeautifulSoup以及bs4.element.Tag对象能够使用find_all方法

        html_soup.find_all('li'):查找所有li标签
        html_soup.find_all(['li','a']):查找所有li标签和a标签
        html_soup.find_all(re.compile('^b')): 查找所有符合正则表达式的标签
        html_soup.find_all(name='ul',attrs={'class':'article'})
        html_soup.find_all(name='ul', attrs={'id': 'Ul1'})
    
  • . 点表示类选择器
     html_soup = BeautifulSoup(response.text,'html.parser')
     publish_time = html_soup.select('span.fn-left')
    
  • # 表示id选择器
     html_soup = BeautifulSoup(response.text,'html.parser')
     id_li = html_soup.select('li#ad_tw_04')[0]
    

栗子又说:“在来一次啊~~~~~~”

from lxml import etree
import requests
	response = requests.get('https://bj.lianjia.com/zufang')
		#首先创建一个soup对象
        #'lxml':说明使用的是lxml.html解析器(速度快,容错性也比较高)
        #'html.parser':python模块自带的html解析器
   html = BeautifulSoup(response.text,'html.parser')
    ul_list = html.select('ul#house-lst li')
    for li in ul_list:
        dic = {}
        # 图片链接
        dic['img_url'] = li.select('div.pic-panel img')[0].attrs['src']
        # print(dic['img_url'])
        # 标题
        dic['title'] = li.select('div.info-panel h2 a')[0].get_text()
        print(dic['title'])

pyQuery

  • 构建pyQuery对象的方式:
    • pq_html = pq(response.text) —> 直接传入网页源码
    • pq_html1 = pq(etree.fromstring(response.text)) ----> 传入lxml解析以后的html
    • pq_html2 = pq(‘https://ww.baidu.com’) —>传入url pyQuery会自己请求,拿到请求结果,
      不推荐使用,对于复杂的url pyQuery 并不能很友好
    • pq_html4 = pq(filename=‘filename’) —> 直接传入文件 并解析
  • 提取数据
    • 直接使用CSS语法 提取
      pq_html = pq(response.text)
      print(type(pq_html))
      tr = pq_html('tr.even')
      print(type(tr))
      
    • 注意: 这时候 tr 任然是 pyQuery对象
    • 注意: 如果想遍历 itemss() 转成生成器(generator)
      tr_list = tr.items('td') # 这里表示遍历tr 子节点的td标签
      # 如果不加参数 则表明不按理tr标签  
      
      print(type(tr_list))
      for i in tr_list:
          print(i)
          print(type(i))
      
      
    • 进一步提取
      • .html() 表示获取某一块代码块
      • .text() 表示获取文本内容
      • .attr() 获取标签属性值
      • .(select(#/.)) 使用bs4 提取
      • .eq(index索引) 获取某一个标签
      • .find() 找到当前标签下的子节点
      • .filter() 过滤获取节点
      • .addClass(value):添加 class
      • .hasClass(value):—> 判断是否包含指定的 class,返回 True 或 False
      • .children(): —> 获取子元素
      • .parents(): —> 获取父元素
      • .next():—> 获取下一个元素
      • .nextAll(): —> 获取后面全部元素块
      • .not_(selector):–> 获取所有不匹配该选择器的元素

栗子:

if response.status_code == 200:
        print('请求成功')

        #构建一个pq对象
        html_pq = pq(response.text)

        #根据类名赵对应的标签
      #  tr_even = html_pq('tr').filter('.even')
        tr_even = html_pq('tr.even')
        #
        # tr_odd = html_pq('tr').filter('.odd')
        tr_odd = html_pq('tr.odd')
        jobs = tr_even + tr_odd
        print(type(jobs))

        #PyQuer对像不是一个可迭代对象,
        # print(type(jobs.items()))
        for tr in jobs.items():
            # print(tr)
            #提取想要的数据
            #.text()获取标签的文本
            title = tr('td.l.square a').text()
            print(title)
            #.attr('href')获取标签的属性
            url = tr('td.l.square a').attr('href')
            print(url)
            #获取类型
            #.eq(1) 根据索引取标签,所以从0开始
            tags = tr('td').eq(1).text()
            print(tags)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值