How can I turn nodes that made in shader editor to script?
If I understand correctly you want to turn your material into its equivalent python nodes. Arguably this is a bit too involved for a single SE question because there are a lot of use cases. Thankfully I tackled this some months ago for a personal project so I can share what I worked on.
You'll need to learn how to use a script.
How to use :
Select your object, select the material you want to copy, run the script. The material code will be added in a new text block.

&quot;&quot;&quot;
This scripts &quot;serializes&quot; the active material of the currently selected object
And creates a script readable by the Blender API to recreate said Material.
As any Blender script, it is free to use in any way shape or form.
V 1.1 - 20.10.23
Fixed NodeSocketVirtual error
&quot;&quot;&quot;

import bpy

from bpy.types import (
    NodeSocketShader,
    NodeSocketVirtual,
    NodeSocketVector,
    NodeSocketVectorDirection,
    NodeSocketVectorXYZ,
    NodeSocketVectorTranslation,
    NodeSocketVectorEuler,
    NodeSocketColor,

    NodeReroute,

    Object,
    Image,
    ImageUser,
    Text,
    ParticleSystem,
    CurveMapping,
    ColorRamp,

    ShaderNodeTree,
)

from mathutils import Vector, Color


ERROR = &quot;~ ERROR ~&quot;

def get_link_statement(link):
    &quot;&quot;&quot;
    Build the statement to re-create given link
    &quot;&quot;&quot;
    return f&quot;&quot;&quot;\
links.new({link.from_node.path_from_id()}.outputs[{get_socket_index(link.from_socket)}]\
, {link.to_node.path_from_id()}.inputs[{get_socket_index(link.to_socket)}])\
    &quot;&quot;&quot;


def value_from_socket(socket):
    &quot;&quot;&quot;
    Returns the evaluated value of a node socket's default value
    &quot;&quot;&quot;
    # A Shader socket (green dot) doesn't have a default value :
    if isinstance(socket, (NodeSocketShader, NodeSocketVirtual)):
        return ERROR
    elif isinstance(socket, (
            NodeSocketVector,
            NodeSocketVectorXYZ,
            NodeSocketVectorTranslation,
            NodeSocketVectorEuler,
            NodeSocketVectorDirection)):
        return f&quot;{[socket.default_value[i] for i in range(3)]}&quot;
    elif isinstance(socket, NodeSocketColor):
        return f&quot;{[socket.default_value[i] for i in range(4)]}&quot;
    else:
        return socket.default_value.__str__()


class NodeCreator:
    &quot;&quot;&quot;
    Helper class to programmatically recreate the passed node
    &quot;&quot;&quot;
    # These props are internal or read-only
    # and aren't useful in the serialization.
    default_props = (
        &quot;dimensions&quot;,
        &quot;draw_buttons&quot;,
        &quot;draw_buttons_ext&quot;,
        &quot;input_template&quot;,
        &quot;inputs&quot;,
        &quot;internal_links&quot;,
        &quot;isAnimationNode&quot;,
        &quot;is_registered_node_type&quot;,
        &quot;output_template&quot;,
        &quot;outputs&quot;,
        &quot;poll&quot;,
        &quot;poll_instance&quot;,
        &quot;rna_type&quot;,
        &quot;socket_value_update&quot;,
        &quot;type&quot;,
        &quot;update&quot;,
        &quot;viewLocation&quot;,

        &quot;texture_mapping&quot;,
        &quot;color_mapping&quot;,

        &quot;filepath&quot;,

        &quot;cache_point_density&quot;,
        &quot;calc_point_density&quot;,
        &quot;calc_point_density_minmax&quot;,

        &quot;interface&quot;,

        &quot;height&quot;,
        &quot;show_options&quot;,
        &quot;show_preview&quot;,
        &quot;show_texture&quot;,
        &quot;width_hidden&quot;,
    )

    def __init__(self, node):
        &quot;&quot;&quot;
        Initialize the node inputs and outputs,
        and the different fields' default values
        &quot;&quot;&quot;
        self.node = node
        self.input_default_values = []
        self.output_default_values = []
        if not isinstance(node, NodeReroute):
            for _input in node.inputs:
                self.input_default_values.append(value_from_socket(_input))
            for output in node.outputs:
                self.output_default_values.append(value_from_socket(output))

        self.type = type(node).__name__
        self.properties = []  # Could use an ordered dict instead.
        for prop_name in dir(node):
            if prop_name.startswith(&quot;_&quot;) or prop_name.startswith(&quot;bl_&quot;):
                continue
            if prop_name in NodeCreator.default_props:
                continue
            self.properties.append((prop_name, getattr(node, prop_name)))

    def statements(self):
        &quot;&quot;&quot;
        Build the chain of statements to programmatically recreate the node
        &quot;&quot;&quot;
        statements = []
        statements.append(f&quot;new_node = nodes.new(type='{self.type}')&quot;)
        self.properties = sorted(self.properties, key=lambda p: p[0])
        for props_tuple in self.properties:
            prop, value = props_tuple
            if isinstance(value, ImageUser):
                statements.append(f&quot;&quot;&quot;\
img_text = new_node.{prop}
img_text.frame_current = {value.frame_current}
img_text.frame_duration = {value.frame_duration}
img_text.frame_offset = {value.frame_offset}
img_text.frame_start = {value.frame_start}
img_text.use_auto_refresh = {value.use_auto_refresh}
img_text.use_cyclic = {value.use_cyclic}
img_text.tile = {value.tile}\
                &quot;&quot;&quot;)
                continue
            if isinstance(value, ParticleSystem):
                # /!\ Make sure this is executed after node.object statement
                statements.append(f&quot;&quot;&quot;\
if new_node.object:
    new_node.{prop} = new_node.object.particle_systems.get('{value.name}')
                &quot;&quot;&quot;)
                continue
            if isinstance(value, CurveMapping):
                statements.append(f&quot;&quot;&quot;\
map = new_node.{prop}
map.clip_max_x = {value.clip_max_x}
map.clip_max_y = {value.clip_max_y}
map.clip_min_x = {value.clip_min_x}
map.clip_min_y = {value.clip_min_y}
map.tone = '{value.tone}'
map.use_clip = {value.use_clip}\
                &quot;&quot;&quot;)
                # Remove the 2 starting default points and only these :
                for i, curve in enumerate(value.curves):
                    statements.append(f&quot;map_c = map.curves[{i}]&quot;)
                    for point in curve.points:
                        statements.append(f&quot;&quot;&quot;\
map_c.points.new({point.location[0]}, {point.location[1]})&quot;&quot;&quot;)
                    statements.append(&quot;&quot;&quot;\
removed_start = removed_end = False
for i in range(len(map_c.points) - 1, -1, -1):
    p = map_c.points[i]
    if not removed_start and p.location[0] == map.clip_min_x and p.location[1] == map.clip_min_y:
        map_c.points.remove(p)
        removed_start = True
    if not removed_end and p.location[0] == 1 and p.location[1] == 1:
        map_c.points.remove(p)
        removed_end = True\
                    &quot;&quot;&quot;)
                statements.append(f&quot;map.update()&quot;)
                continue
            if isinstance(value, ColorRamp):
                statements.append(f&quot;&quot;&quot;\
cr = new_node.{prop}
cr.color_mode = '{value.color_mode}'
cr.hue_interpolation = '{value.hue_interpolation}'
cr.interpolation = '{value.interpolation}'\
                &quot;&quot;&quot;)
                for stop in value.elements:
                    statements.append(f&quot;&quot;&quot;new_stop = cr.elements.new({stop.position})
new_stop.color = {[ch for ch in stop.color]}&quot;&quot;&quot;)
                # Remove the 2 starting default stops and only these :
                statements.append(&quot;&quot;&quot;\
removed_black = removed_white = False
for i in range(len(cr.elements) - 1, -1, -1):
    stop = cr.elements[i]
    if not removed_black and stop.position == 0 and all([stop.color[i] == (0, 0, 0, 1)[i] for i in range(4)]):
        cr.elements.remove(stop)
        removed_black = True
    if not removed_white and stop.position == 1 and all([stop.color[i] == (1, 1, 1, 1)[i] for i in range(4)]):
        cr.elements.remove(stop)
        removed_white = True\
                &quot;&quot;&quot;)
                continue
            if isinstance(value, ShaderNodeTree):
                statements.append(f&quot;&quot;&quot;\
ng = bpy.data.node_groups.get('{value.name}')
if not ng:
    new_node.label = \&quot;Missing Node Group : '{value.name}'\&quot;
else:
    new_node.{prop} = ng\
                &quot;&quot;&quot;)
                continue

            if prop in (&quot;hide&quot;, &quot;mute&quot;, &quot;use_custom_color&quot;):
                if value:
                    statements.append(f&quot;new_node.{prop} = {value}&quot;)
            elif prop == &quot;text&quot; and not value:
                continue
            elif prop in (&quot;select&quot;, &quot;shrink&quot;):
                if not value:
                    statements.append(f&quot;new_node.{prop} = {value}&quot;)
            elif isinstance(value, str):
                if value:
                    statements.append(f&quot;new_node.{prop} = '{value}'&quot;)
            elif isinstance(value, Vector):
                if len(value) == 2:
                    statements.append(
                        f&quot;new_node.{prop} = ({value[0]}, {value[1]})&quot;)
                else:
                    statements.append(
                        f&quot;new_node.{prop} = ({value[0]}, {value[1]}, {value[2]})&quot;)
            elif isinstance(value, Object):
                statements.append(
                    f&quot;new_node.{prop} = bpy.data.objects.get('{value.name}')&quot;)
            elif isinstance(value, Image):
                statements.append(
                    f&quot;new_node.{prop} = bpy.data.images.get('{value.name}')&quot;)
            elif isinstance(value, Text):
                if value:
                    statements.append(
                        f&quot;new_node.{prop} = bpy.data.texts.get('{value.name}')&quot;)
            elif prop == &quot;parent&quot;:
                if value:
                    statements.append(f&quot;&quot;&quot;\
parent = nodes.get('{value.name}')
if parent:
    new_node.parent = parent
    while True:
        new_node.location += parent.location
        if parent.parent:
            parent = parent.parent
        else:
            break\
                    &quot;&quot;&quot;)
            elif isinstance(value, Color):
                statements.append(
                    f&quot;new_node.{prop} = ({value[0]}, {value[1]}, {value[2]})&quot;)
            else:
                statements.append(f&quot;new_node.{prop} = {value}&quot;)
        for i, dv in enumerate(self.input_default_values):
            if dv == ERROR:
                continue
            statements.append(f&quot;new_node.inputs[{i}].default_value = {dv}&quot;)

        for i, dv in enumerate(self.output_default_values):
            if dv == ERROR:
                continue
            statements.append(f&quot;new_node.outputs[{i}].default_value = {dv}&quot;)

        if not isinstance(self.node, NodeReroute):
            for _input in self.node.inputs:
                if _input.hide:
                    statements.append(
                        f&quot;new_node.inputs[{get_socket_index(_input)}].hide = True&quot;)
            for output in self.node.outputs:
                if output.hide:
                    statements.append(
                        f&quot;new_node.outputs[{get_socket_index(output)}].hide = True&quot;)
#        DEBUG Print node location as a label :
#        statements.append(&quot;new_node.label = str(new_node.location[0]).split('.')[0] + ', ' + str(new_node.location[1]).split('.')[0]&quot;)

        return statements


def serialize_material(mat):
    &quot;&quot;&quot;
    Returns the ordered statements necessary to build the 
    Mateiral generation script
    &quot;&quot;&quot;
    node_tree = mat.node_tree
    statements = [f&quot;&quot;&quot;\
import bpy
new_mat = bpy.data.materials.get('{mat.name}')
if not new_mat:
    new_mat = bpy.data.materials.new('{mat.name}')
    
new_mat.use_nodes = True
node_tree = new_mat.node_tree
nodes = node_tree.nodes
nodes.clear()
    
links = node_tree.links
links.clear()
    &quot;&quot;&quot;]

    statements.append(&quot;# Nodes :\n&quot;)
    for node in node_tree.nodes:
        for st in NodeCreator(node).statements():
            statements.append(st)
        statements.append(&quot;&quot;)

    if node_tree.links:
        statements.append(&quot;# Links :\n&quot;)
        for link in node_tree.links:
            statements.append(get_link_statement(link))

    return statements


def write_material_to_text_block(obj):
    &quot;&quot;&quot;
    Create or overwrite a text block with the same name as the material
    Which contains all the necessary statements to duplicate the material
    &quot;&quot;&quot;
    if not obj or obj.type not in ('MESH', 'CURVE', 'VOLUME', 'SURFACE', 'FONT', 'META', 'GPENCIL'):
        return
    am = obj.active_material
    if not am or not am.use_nodes:
        return
    statements = serialize_material(am)

    text_block = bpy.data.texts.get(am.name)
    if text_block:
        text_block.clear()
    else:
        text_block = bpy.data.texts.new(am.name)

    for st in statements:
        text_block.write(st)
        text_block.write(&quot;\n&quot;)

    return text_block


def get_socket_index(socket):
    return socket.path_from_id().split(&quot;.&quot;)[-1].split(&quot;[&quot;)[-1][:-1]


if __name__ == &quot;__main__&quot;:
    text_block = write_material_to_text_block(bpy.context.active_object)

The code is available there for grabbing
https://github.com/Gorgious56/Material2Script/blob/main/material_to_script.py