【数据提取Xpath/BeautifulSoup4】

数据提取-Xpath

lxml是python的第三方解析库,能够高效地解析HTML/XML文档。

安装:在cmd窗口输入 pip install lxml

使用:

  • 导入模块 from lxml import etree
  • 创建解析对象 parse_html = etree.HTML(html)
  • 解析对象调用 xpath:r_list = parse_html.xpath('xpath语法')

xpath语法

表达式 描述
// 从匹配选择的当前节点选择文档中的节点,不考虑他们的位置
/ 某节点下的某个节点
@ 选取某个节点的属性
text() 选取文本

获取到所有li下的class属性值

print(html.xpath('//li/@class'))

获取到所有li下a标签的href

print(html.xpath('//li/a/@href'))

获取到所有li下a标签的文字

print(html.xpath('//li/a/text()'))

谓语:查找某个特定节点或者包含某个指定的值的节点,被嵌在方括号中。

表达式 描述
/bookstore/book[1] 选取属于bookstore子元素的第一个book元素
/bookstore/book[last()] 选取属于bookstore子元素的最后一个book元素
//title[@lang] 选取所有名为lang的属性的title元素

 


获取科目一的题目,选项,答案和图片

import requests

from lxml import etree
# 面向对象
class JsyKs:
    def __init__(self):
        self.url = 'https://www.jsyks.com/kmy-mnks'
        self.headers = {
            "User - Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
        }
    def get_html(self, url):
        '''发送请求的方法'''
        response = requests.get(url, headers=self.headers)
        return response.text

    def parse_html(self, html):
        '''提取数据'''
        html = etree.HTML(html)    # 解析对象
        lis = html.xpath('//ul[@class="Content"]/li')    # 找到类名为Content的ul标签下的li标签
        for li in lis:
            # 考试题目
            title = li.xpath('./strong/text()')[0]
            # 选项
            option = li.xpath('./b/text()')
            # 答案
            k = li.xpath('./@k')[0]

            # 获取图片
            img_src = li.xpath('./strong/u/img/@src')
            img_ybsrc = li.xpath('./strong/u/img/@ybsrc')
            img_url = img_src or img_ybsrc
            if img_url:
                img_url = f'https:{img_url[0]}'
            else:
                img_url = None
            print('-'*100)
            print(title)
            print(img_url)
            print(option)
            print()
            print(k)


    def run(self):
        html = self.get_html(self.url)
        self.parse_html(html)

spider = JsyKs()
spider.run()

正则表达式的使用

import re

import requests

url = 'https://hifini.com/thread-906.htm'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
}
response = requests.get(url, headers=headers)
html = response.text
# print(html)
r_list = re.findall("url: '(.*?)',", html)[0]
song_url = "https://hifini.com/" + r_list
data_bytes = requests.get(song_url, headers=headers).content
with open('1.mp3', 'wb')as f:
    f.write(data_bytes)

数据提取-BeautifulSoup4

和lxml一样,它也是一个HTML/XML的解析器,主要功能是解析和提取HTML/XML数据。

安装:pip install bs4

常见对象

Tag:是HTML的一个标签,查找的是在所有内容中第一个符合要求的标签

NavigableString:如果拿到标签后还想获取标签中的内容可以通过tag.string来获取

  • string:获取某个标签下的非标签字符串。返回的是字符串。但如果这个标签下有多行字符就获取不到了。
  • strings:获取某个标签下的子孙非标签字符串。返回的是一个生成器(可以被循环)。
  • stripped_strings:获取某个标签下的子孙非标签字符串,会去掉空白字符。返回的是生成器。

获取多行标签的内容:

soup = BeautifulSoup(string, "lxml")

print(list(soup.url.stripped_strings))

获取标签属性:

print(soup.a["href"])

 find与find_all

找到id为item-1的标签

print(soup.find('li', id='item-1'))

找到类名为item-1的标签

print(soup.find('li', class_='item-1'))           # (class_与class区分开来)

使用find_all寻找

print(soup.find_all('li'))     #拿到所有的li标签

print(soup.find_all('li', limit=2))    # 拿到前两个li标签  

import requests

from bs4 import BeautifulSoup


class DouBan(object):
    def __init__(self):
        self.url = 'https://www.douban.com/doulist/1518184/?start={}&sort=seq&playable=0&sub_type='
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
        }

    def get_html(self, url):
        response = requests.get(url, headers=self.headers)
        return response.text

    def get_detail_url(self, url):
        html = self.get_html(url)
        soup = BeautifulSoup(html, 'lxml')
        # 在页面上找一个叫div且类名为article的标签,再找到该标签下的所有类名为title的div标签
        lis = soup.find("div", class_="article").find_all('div', class_="title")    # 从大方向上找,所有的小盒子的父级以及他们相同点
        detail_urls = []
        # lis = soup.find("div", class_="title")
        for li in lis:
            detail_url = li.find('a')['href']
            detail_urls.append(detail_url)
        return detail_urls

    def get_movie_info(self, detail_url):
        print(detail_url)    # 详细信息
        html = self.get_html(detail_url)
        soup = BeautifulSoup(html, 'lxml')   # 转换成一个数据对象
        # 使用join把列表转为字符串输出
        # 使用join前:['肖申克的救赎 The Shawshank Redemption', '(1994)']
        name = "".join(list(soup.find('h1').stripped_strings))   # 写上需要的文字被包裹着的上一级标签.值得注意的是:在这里面你所要寻找的内容是跳转后的页面,建议跳转页面之后在找到需要的内容标签后再写出。
        # 使用join后:肖申克的救赎 The Shawshank Redemption(1994)
        actor = list(soup.find('span', class_='actor').find('span', class_='attrs').stripped_strings)    # 找电影的主演(一层一层,更进一步)
        print("".join(actor))    # 将内容拼接在一起
        print(name)

    def run(self):
        # 1.获取到每一页的url
        for start in range(0, 226, 25):
            url = self.url.format(start)
            # 2.给获取到的url发送请求获取到详细页面
            detail_urls = self.get_detail_url(url)
            for detail_url in detail_urls:
                # 3.获取详情页面里面的数据
                self.get_movie_info(detail_url)
            break    # 先获取第一页的数据

spider = DouBan()
spider.run()

select方法

通过标签名查找:

soup.select('a')

通过类名查找:

soup.select('.title')

通过id查找:

soup.select('#link1')

组合查找:

soup.select("p #link1")

soup.select("div > box")

 

 

你可能感兴趣的:(python)